From c0e01bce21b06bf9e62d9f2bf436ad93914512e8 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Fri, 25 Dec 2020 21:00:58 +0100 Subject: more testing --- emu/6502.c | 2 +- emu/tests/test_cpu_6502.c | 463 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 463 insertions(+), 2 deletions(-) (limited to 'emu') diff --git a/emu/6502.c b/emu/6502.c index ff178f9..cab72b3 100644 --- a/emu/6502.c +++ b/emu/6502.c @@ -372,7 +372,7 @@ void cpu_6502_step( cpu_6502_t *cpu ) case SBC_IMM: operand8 = cpu_6502_read_byte( cpu, cpu->PC ); cpu->PC++; - tmp = cpu->A - operand8 - ( cpu_6502_is_carry( cpu ) ? 0 : 1 ); + tmp = cpu->A - operand8 - ( cpu_6502_is_carry( cpu ) ? 1 : 0 ); update_negative_and_sign( cpu, tmp ); if( tmp & 0xFF00 ) { cpu->PS |= PS_C; diff --git a/emu/tests/test_cpu_6502.c b/emu/tests/test_cpu_6502.c index b926c1a..86d1115 100644 --- a/emu/tests/test_cpu_6502.c +++ b/emu/tests/test_cpu_6502.c @@ -562,6 +562,273 @@ START_TEST( test_cpu_6502_inc_flags_zero ) } END_TEST +// INX + +START_TEST( test_cpu_6502_inx_flags_positive ) +{ + INIT_CPU_TEST + + CODE_SET1( 0xc8 ); // INX + + cpu.Y = 0x34; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); + ck_assert( !cpu_6502_is_zero( &cpu ) ); + ck_assert( !cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, 0x35 ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + +START_TEST( test_cpu_6502_inx_flags_negative ) +{ + INIT_CPU_TEST + + CODE_SET1( 0xc8 ); // INX + + cpu.Y = 0xf6; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); + ck_assert( !cpu_6502_is_zero( &cpu ) ); + ck_assert( cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, 0xf7 ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + +START_TEST( test_cpu_6502_inx_flags_zero ) +{ + INIT_CPU_TEST + + CODE_SET1( 0xc8 ); // INX + + cpu.Y = 0xff; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); + ck_assert( cpu_6502_is_zero( &cpu ) ); + ck_assert( !cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, 0x00 ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + +// DEX + +START_TEST( test_cpu_6502_dex_flags_positive ) +{ + INIT_CPU_TEST + + CODE_SET1( 0xca ); // DEX + + cpu.X = 0x56; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); + ck_assert( !cpu_6502_is_zero( &cpu ) ); + ck_assert( !cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, 0x55 ); + ck_assert_int_eq( cpu.Y, before_cpu.Y ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + +START_TEST( test_cpu_6502_dex_flags_negative ) +{ + INIT_CPU_TEST + + CODE_SET1( 0xca ); // DEX + + cpu.X = 0x93; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); + ck_assert( !cpu_6502_is_zero( &cpu ) ); + ck_assert( cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, 0x92 ); + ck_assert_int_eq( cpu.Y, before_cpu.Y ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + +START_TEST( test_cpu_6502_dex_flags_zero ) +{ + INIT_CPU_TEST + + CODE_SET1( 0xca ); // DEX + + cpu.X = 0x01; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); + ck_assert( cpu_6502_is_zero( &cpu ) ); + ck_assert( !cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, 0x00 ); + ck_assert_int_eq( cpu.Y, before_cpu.Y ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + +// DEY + +START_TEST( test_cpu_6502_dey_flags_positive ) +{ + INIT_CPU_TEST + + CODE_SET1( 0x88 ); // DEY + + cpu.Y = 0x56; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); + ck_assert( !cpu_6502_is_zero( &cpu ) ); + ck_assert( !cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, 0x55 ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + +START_TEST( test_cpu_6502_dey_flags_negative ) +{ + INIT_CPU_TEST + + CODE_SET1( 0x88 ); // DEY + + cpu.Y = 0x93; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); + ck_assert( !cpu_6502_is_zero( &cpu ) ); + ck_assert( cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, 0x92 ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + +START_TEST( test_cpu_6502_dey_flags_zero ) +{ + INIT_CPU_TEST + + CODE_SET1( 0x88 ); // DEY + + cpu.Y = 0x01; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_N | PS_Z ), before_cpu.PS & ~( PS_N | PS_Z ) ); + ck_assert( cpu_6502_is_zero( &cpu ) ); + ck_assert( !cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, 0x00 ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + // ROL START_TEST( test_cpu_6502_rol_flags_accumulator_carry ) @@ -595,6 +862,98 @@ START_TEST( test_cpu_6502_rol_flags_accumulator_carry ) } END_TEST +// CPX + +START_TEST( test_cpu_6502_cpx_flags_equals ) +{ + INIT_CPU_TEST + + CODE_SET2( 0xe0, 0x10 ); // CPX #$10 + + cpu.X = 0x10; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_C | PS_N | PS_Z ), before_cpu.PS & ~( PS_C | PS_N | PS_Z ) ); + ck_assert( cpu_6502_is_carry( &cpu ) ); + ck_assert( cpu_6502_is_zero( &cpu ) ); + ck_assert( !cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, before_cpu.Y ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + +START_TEST( test_cpu_6502_cpx_flags_less ) +{ + INIT_CPU_TEST + + CODE_SET2( 0xe0, 0x10 ); // CPX #$10 + + cpu.X = 0x01; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_C | PS_N | PS_Z ), before_cpu.PS & ~( PS_C | PS_N | PS_Z ) ); + ck_assert( !cpu_6502_is_carry( &cpu ) ); + ck_assert( !cpu_6502_is_zero( &cpu ) ); + ck_assert( cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, before_cpu.Y ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + +START_TEST( test_cpu_6502_cpx_flags_greater ) +{ + INIT_CPU_TEST + + CODE_SET2( 0xe0, 0x10 ); // CPX #$10 + + cpu.X = 0x20; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS & ~( PS_C | PS_N | PS_Z ), before_cpu.PS & ~( PS_C | PS_N | PS_Z ) ); + ck_assert( cpu_6502_is_carry( &cpu ) ); + ck_assert( !cpu_6502_is_zero( &cpu ) ); + ck_assert( !cpu_6502_is_negative( &cpu ) ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, before_cpu.Y ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + // BCC START_TEST( test_cpu_6502_bcc_carry_clear ) @@ -651,6 +1010,62 @@ START_TEST( test_cpu_6502_bcc_carry_set ) } END_TEST +// BNE + +START_TEST( test_cpu_6502_bne_zero_clear ) +{ + INIT_CPU_TEST + + CODE_SET2( 0xD0, 0x12 ); // BNE $12 + + cpu.PS &= ~PS_Z; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC + 2 + 0x12 ); // zero is clear, jump taken + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS, before_cpu.PS ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, before_cpu.Y ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + +START_TEST( test_cpu_6502_bne_zero_set ) +{ + INIT_CPU_TEST + + CODE_SET2( 0xD0, 0x12 ); // BNE $12 + + cpu.PS |= PS_Z; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, before_cpu.PC+2 ); // zero is set, execute next opcode, don't jump + ck_assert_int_eq( cpu.SP, before_cpu.SP ); + ck_assert_int_eq( cpu.PS, before_cpu.PS ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, before_cpu.Y ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + // JMP START_TEST( test_cpu_6502_jmp_abs ) @@ -701,7 +1116,7 @@ START_TEST( test_cpu_6502_jsr_abs ) ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, before_cpu.X ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); - ck_assert_mem_eq( &ram.cell[0x0], &before_ram.cell[0x0], 0x1FF - 2 ); + ck_assert_mem_eq( &ram.cell[0x0], &before_ram.cell[0x0], 0x1fd ); ck_assert_int_eq( ram.cell[0x01fe], 0x02 ); // next PC after return on stack ck_assert_int_eq( ram.cell[0x01ff], 0xf8 ); @@ -709,6 +1124,37 @@ START_TEST( test_cpu_6502_jsr_abs ) } END_TEST +// RTS + +START_TEST( test_cpu_6502_rts ) +{ + INIT_CPU_TEST + + CODE_SET1( 0x60 ); // RTS + + cpu.SP = 0xfd; + ram.cell[0x01fe] = 0x02; + ram.cell[0x01ff] = 0xf8; + + COPY_CPU_TEST + + cpu_6502_run( &cpu, 1 ); + + PRINT_CPU_TEST + + ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); + ck_assert_int_eq( cpu.PC, 0xf802 + 1 ); // PC restored to the value on the stack + ck_assert_int_eq( cpu.SP, 0xff ); // stack empty + ck_assert_int_eq( cpu.PS, before_cpu.PS ); + ck_assert_int_eq( cpu.A, before_cpu.A ); + ck_assert_int_eq( cpu.X, before_cpu.X ); + ck_assert_int_eq( cpu.Y, before_cpu.Y ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + DEINIT_CPU_TEST +} +END_TEST + static void create_cpu_6502_testcase( Suite *suite, const char *name, const TTest *test_func ) { TCase *tc; @@ -741,11 +1187,26 @@ static Suite *make_cpu_6502_testsuite( void ) create_cpu_6502_testcase( suite, "INC (flags, positive)", test_cpu_6502_inc_flags_positive ); create_cpu_6502_testcase( suite, "INC (flags, negative)", test_cpu_6502_inc_flags_negative ); create_cpu_6502_testcase( suite, "INC (flags, zero)", test_cpu_6502_inc_flags_zero ); + create_cpu_6502_testcase( suite, "INX (flags, positive)", test_cpu_6502_inx_flags_positive ); + create_cpu_6502_testcase( suite, "INX (flags, negative)", test_cpu_6502_inx_flags_negative ); + create_cpu_6502_testcase( suite, "INX (flags, zero)", test_cpu_6502_inx_flags_zero ); + create_cpu_6502_testcase( suite, "DEX (flags, positive)", test_cpu_6502_dex_flags_positive ); + create_cpu_6502_testcase( suite, "DEX (flags, negative)", test_cpu_6502_dex_flags_negative ); + create_cpu_6502_testcase( suite, "DEX (flags, zero)", test_cpu_6502_dex_flags_zero ); + create_cpu_6502_testcase( suite, "DEY (flags, positive)", test_cpu_6502_dey_flags_positive ); + create_cpu_6502_testcase( suite, "DEY (flags, negative)", test_cpu_6502_dey_flags_negative ); + create_cpu_6502_testcase( suite, "DEY (flags, zero)", test_cpu_6502_dey_flags_zero ); create_cpu_6502_testcase( suite, "ROL (flags, carry)", test_cpu_6502_rol_flags_accumulator_carry ); + create_cpu_6502_testcase( suite, "CPX (flags, equals)", test_cpu_6502_cpx_flags_equals ); + create_cpu_6502_testcase( suite, "CPX (flags, less)", test_cpu_6502_cpx_flags_less ); + create_cpu_6502_testcase( suite, "CPX (flags, greater)", test_cpu_6502_cpx_flags_greater ); create_cpu_6502_testcase( suite, "BCC (branch taken, carry clear)", test_cpu_6502_bcc_carry_clear ); create_cpu_6502_testcase( suite, "BCC (branch not taken, carry set)", test_cpu_6502_bcc_carry_set ); + create_cpu_6502_testcase( suite, "BNE (branch not taken, zero clear)", test_cpu_6502_bne_zero_clear ); + create_cpu_6502_testcase( suite, "BNE (branch taken, zero set)", test_cpu_6502_bne_zero_set ); create_cpu_6502_testcase( suite, "JMP (absolute)", test_cpu_6502_jmp_abs ); create_cpu_6502_testcase( suite, "JSR (absolute)", test_cpu_6502_jsr_abs ); + create_cpu_6502_testcase( suite, "RTS", test_cpu_6502_rts ); return suite; } -- cgit v1.2.3-54-g00ecf