From 8dde478cfc2174f198290be40a633a4c9c9db833 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 12 Dec 2020 20:14:45 +0100 Subject: some more testing --- emu/6502.c | 63 ++++++++++++++++-------------- emu/6502.h | 12 ++++++ emu/device.c | 7 ++++ emu/device.h | 1 + emu/memory.c | 9 +++++ emu/memory.h | 1 + emu/tests/check_unittest.xslt | 2 +- emu/tests/test_cpu_6502.c | 90 ++++++++++++++++++++++++++++++++++++++----- 8 files changed, 146 insertions(+), 39 deletions(-) diff --git a/emu/6502.c b/emu/6502.c index 139b6f6..ff178f9 100644 --- a/emu/6502.c +++ b/emu/6502.c @@ -116,37 +116,37 @@ static void handle_sign( cpu_6502_t *cpu, uint8_t x ) } } -static bool is_negative( cpu_6502_t *cpu ) +bool cpu_6502_is_negative( cpu_6502_t *cpu ) { return cpu->PS & PS_N; } -static bool is_overflow( cpu_6502_t *cpu ) +bool cpu_6502_is_overflow( cpu_6502_t *cpu ) { return cpu->PS & PS_V; } -static bool is_brk( cpu_6502_t *cpu ) +bool cpu_6502_is_brk( cpu_6502_t *cpu ) { return cpu->PS & PS_B; } -static bool is_decimal( cpu_6502_t *cpu ) +bool cpu_6502_is_decimal( cpu_6502_t *cpu ) { return cpu->PS & PS_D; } -static bool is_interrupt( cpu_6502_t *cpu ) +bool cpu_6502_is_interrupt( cpu_6502_t *cpu ) { return cpu->PS & PS_I; } -static bool is_zero( cpu_6502_t *cpu ) +bool cpu_6502_is_zero( cpu_6502_t *cpu ) { return cpu->PS & PS_Z; } -static bool is_carry( cpu_6502_t *cpu ) +bool cpu_6502_is_carry( cpu_6502_t *cpu ) { return cpu->PS & PS_C; } @@ -198,6 +198,19 @@ void cpu_6502_get_opcode_mnemonic( cpu_6502_t *cpu, char *buf, int buflen, uint1 snprintf( buf, buflen, "%s (%02X)", mnemonic[opcode], opcode ); } + +void cpu_6502_print_debug( cpu_6502_t *cpu ) +{ + if( cpu->debug_flags & DEBUG_STATUS ) { + cpu_6502_print_state( cpu, cpu->PC-1 ); + } + if( cpu->debug_flags & DEBUG_STACK ) { + cpu_6502_print_stack( cpu ); + } + if( cpu->debug_flags & DEBUG_ZERO_PAGE ) { + cpu_6502_print_zerop_page( cpu ); + } +} void cpu_6502_print_state( cpu_6502_t *cpu, uint16_t addr ) { @@ -207,13 +220,13 @@ void cpu_6502_print_state( cpu_6502_t *cpu, uint16_t addr ) fprintf( stderr, "PC: %04X SP: 01%02X PS: %02X %c%c-%c%c%c%c%c A: %02X X: %02X Y: %02X steps: %d OP: %s\n", cpu->PC, cpu->SP, cpu->PS, - is_negative( cpu ) ? 'N' : 'n', - is_overflow( cpu ) ? 'V' : 'v', - is_brk( cpu ) ? 'B' : 'b', - is_decimal( cpu ) ? 'D' : 'd', - is_interrupt( cpu ) ? 'I' : 'i', - is_zero( cpu ) ? 'Z' : 'z', - is_carry( cpu ) ? 'C' : 'c', + cpu_6502_is_negative( cpu ) ? 'N' : 'n', + cpu_6502_is_overflow( cpu ) ? 'V' : 'v', + cpu_6502_is_brk( cpu ) ? 'B' : 'b', + cpu_6502_is_decimal( cpu ) ? 'D' : 'd', + cpu_6502_is_interrupt( cpu ) ? 'I' : 'i', + cpu_6502_is_zero( cpu ) ? 'Z' : 'z', + cpu_6502_is_carry( cpu ) ? 'C' : 'c', cpu->A, cpu->X, cpu->Y, cpu->steps, opcode_str ); } @@ -251,16 +264,8 @@ void cpu_6502_step( cpu_6502_t *cpu ) opcode = cpu_6502_read_byte( cpu, cpu->PC ); cpu->PC++; - - if( cpu->debug_flags & DEBUG_STATUS ) { - cpu_6502_print_state( cpu, cpu->PC-1 ); - } - if( cpu->debug_flags & DEBUG_STACK ) { - cpu_6502_print_stack( cpu ); - } - if( cpu->debug_flags & DEBUG_ZERO_PAGE ) { - cpu_6502_print_zerop_page( cpu ); - } + + cpu_6502_print_debug( cpu ); switch( opcode ) { case LDX_IMM: @@ -342,7 +347,7 @@ void cpu_6502_step( cpu_6502_t *cpu ) break; case ROL_ACC: - tmp = ( cpu->A << 1 ) | is_carry( cpu ); + tmp = ( cpu->A << 1 ) | cpu_6502_is_carry( cpu ); if( tmp & 0xFF00 ) { cpu->PS |= PS_C; } else { @@ -367,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 - ( is_carry( cpu ) ? 0 : 1 ); + tmp = cpu->A - operand8 - ( cpu_6502_is_carry( cpu ) ? 0 : 1 ); update_negative_and_sign( cpu, tmp ); if( tmp & 0xFF00 ) { cpu->PS |= PS_C; @@ -385,7 +390,7 @@ void cpu_6502_step( cpu_6502_t *cpu ) case BNE_REL: operand8 = cpu_6502_read_byte( cpu, cpu->PC ); cpu->PC++; - if( !is_zero( cpu ) ) { + if( !cpu_6502_is_zero( cpu ) ) { cpu->PC += (int8_t)operand8; } break; @@ -393,7 +398,7 @@ void cpu_6502_step( cpu_6502_t *cpu ) case BCC_REL: operand8 = cpu_6502_read_byte( cpu, cpu->PC ); cpu->PC++; - if( !is_carry( cpu ) ) { + if( !cpu_6502_is_carry( cpu ) ) { cpu->PC += (int8_t)operand8; } break; @@ -401,7 +406,7 @@ void cpu_6502_step( cpu_6502_t *cpu ) case BCS_REL: operand8 = cpu_6502_read_byte( cpu, cpu->PC ); cpu->PC++; - if( is_carry( cpu ) ) { + if( cpu_6502_is_carry( cpu ) ) { cpu->PC += (int8_t)operand8; } break; diff --git a/emu/6502.h b/emu/6502.h index c3143e7..9dc8614 100644 --- a/emu/6502.h +++ b/emu/6502.h @@ -83,6 +83,7 @@ enum { void cpu_6502_init( cpu_6502_t *cpu, bus_t *bus, bool initialize ); void cpu_6502_reset( cpu_6502_t *cpu ); + uint8_t cpu_6502_read_byte( cpu_6502_t *cpu, uint16_t addr ); uint16_t cpu_6502_read_word( cpu_6502_t *cpu, uint16_t addr ); void cpu_6502_write_byte( cpu_6502_t *cpu, uint16_t addr, uint8_t data ); @@ -90,12 +91,23 @@ void cpu_6502_push_byte( cpu_6502_t *cpu, uint8_t data ); void cpu_6502_push_word( cpu_6502_t *cpu, uint16_t data ); uint8_t cpu_6502_pop_byte( cpu_6502_t *cpu ); uint16_t cpu_6502_pop_word( cpu_6502_t *cpu ); + void cpu_6502_run( cpu_6502_t *cpu, int steps ); void cpu_6502_step( cpu_6502_t *cpu ); + void cpu_6502_get_opcode_mnemonic( cpu_6502_t *cpu, char *buf, int buflen, uint16_t addr ); +void cpu_6502_print_debug( cpu_6502_t *cpu ); void cpu_6502_print_state( cpu_6502_t *cpu, uint16_t addr ); void cpu_6502_print_memory( cpu_6502_t *cpu, uint16_t base, uint8_t size ); void cpu_6502_print_stack( cpu_6502_t *cpu ); void cpu_6502_print_zerop_page( cpu_6502_t *cpu ); +bool cpu_6502_is_negative( cpu_6502_t *cpu ); +bool cpu_6502_is_overflow( cpu_6502_t *cpu ); +bool cpu_6502_is_brk( cpu_6502_t *cpu ); +bool cpu_6502_is_decimal( cpu_6502_t *cpu ); +bool cpu_6502_is_interrupt( cpu_6502_t *cpu ); +bool cpu_6502_is_zero( cpu_6502_t *cpu ); +bool cpu_6502_is_carry( cpu_6502_t *cpu ); + #endif diff --git a/emu/device.c b/emu/device.c index 7ad2741..60d54a1 100644 --- a/emu/device.c +++ b/emu/device.c @@ -20,6 +20,13 @@ void device_init( device_t *device, const char *name ) device->vtable = &device_vtable; } +void device_copy( device_t *to, device_t *from ) +{ + memcpy( to, from, sizeof( device_t ) ); + + to->name = strdup( from->name ); +} + uint8_t device_read( void *obj, uint16_t addr ) { device_t *device = (device_t *)obj; diff --git a/emu/device.h b/emu/device.h index 41c430f..1cf36e7 100644 --- a/emu/device.h +++ b/emu/device.h @@ -27,6 +27,7 @@ typedef struct device_t { } device_t; void device_init( device_t *device, const char *name ); +void device_copy( device_t *to, device_t *from ); uint8_t device_read( void *obj, uint16_t addr ); void device_write( void *obj, uint16_t addr, uint8_t data ); #ifdef WITH_GUI diff --git a/emu/memory.c b/emu/memory.c index c73c668..3ab0694 100644 --- a/emu/memory.c +++ b/emu/memory.c @@ -26,6 +26,15 @@ void memory_init( memory_t *memory, memory_type_t type, uint16_t addr, uint16_t memory->base.vtable = (device_vtable_t *)&memory_vtable; } +void memory_copy( memory_t *to, memory_t *from ) +{ + memcpy( to, from, sizeof( memory_t ) ); + device_copy( &to->base, &from->base ); + + to->cell = malloc( to->size ); + memcpy( to->cell, from->cell, to->size ); +} + void memory_load( memory_t *memory, const char *filename ) { if( memory->type == MEMORY_ROM ) { diff --git a/emu/memory.h b/emu/memory.h index 3a15bfe..1bb8dd8 100644 --- a/emu/memory.h +++ b/emu/memory.h @@ -22,6 +22,7 @@ typedef struct memory_t } memory_t; void memory_init( memory_t *memory, memory_type_t type, uint16_t addr, uint16_t size, bool initialize ); +void memory_copy( memory_t *to, memory_t *from ); void memory_load( memory_t *memory, const char *filename ); void memory_set( memory_t *memory, uint16_t addr, uint8_t *buf, int bufsize ); void memory_reset( memory_t *memory ); diff --git a/emu/tests/check_unittest.xslt b/emu/tests/check_unittest.xslt index b8005fe..2350ff1 100644 --- a/emu/tests/check_unittest.xslt +++ b/emu/tests/check_unittest.xslt @@ -46,7 +46,7 @@ $ xsltproc check_unittest.xslt check_output.xml > check_output.html - + diff --git a/emu/tests/test_cpu_6502.c b/emu/tests/test_cpu_6502.c index 6f53ff0..a6a97cc 100644 --- a/emu/tests/test_cpu_6502.c +++ b/emu/tests/test_cpu_6502.c @@ -51,18 +51,27 @@ void teardown( void ) START_TEST( test_cpu_6502_nop ) { cpu_6502_t before_cpu; + memory_t before_ram; cpu_6502_reset( &cpu ); memory_reset( &rom ); memory_reset( &ram ); + memset( code, 0, ROM_SIZE ); code[0] = 0xea; // NOP codesize = 1; memory_set( &rom, 0x00, code, codesize ); memcpy( &before_cpu, &cpu, sizeof( cpu ) ); + memory_copy( &before_ram, &ram ); + cpu_6502_run( &cpu, 1 ); + fprintf( stderr, "state before:\n" ); + cpu_6502_print_debug( &before_cpu ); + fprintf( stderr, "state after:\n" ); + cpu_6502_print_debug( &cpu ); + 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 ); @@ -70,17 +79,22 @@ START_TEST( test_cpu_6502_nop ) 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 ); + + memory_deinit( &before_ram ); } END_TEST START_TEST( test_cpu_6502_txs ) { cpu_6502_t before_cpu; + memory_t before_ram; cpu_6502_reset( &cpu ); memory_reset( &rom ); memory_reset( &ram ); + memset( code, 0, ROM_SIZE ); code[0] = 0x9a; // TXS codesize = 1; memory_set( &rom, 0x00, code, codesize ); @@ -88,7 +102,14 @@ START_TEST( test_cpu_6502_txs ) cpu.X = 0xff; memcpy( &before_cpu, &cpu, sizeof( cpu ) ); + memory_copy( &before_ram, &ram ); + cpu_6502_run( &cpu, 1 ); + + fprintf( stderr, "state before:\n" ); + cpu_6502_print_debug( &before_cpu ); + fprintf( stderr, "state after:\n" ); + cpu_6502_print_debug( &cpu ); ck_assert_int_eq( cpu.error_state, ERROR_STATE_OK ); ck_assert_int_eq( cpu.PC, before_cpu.PC+1 ); @@ -97,24 +118,75 @@ START_TEST( test_cpu_6502_txs ) ck_assert_int_eq( cpu.A, before_cpu.A ); ck_assert_int_eq( cpu.X, 0xff ); ck_assert_int_eq( cpu.Y, before_cpu.Y ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + memory_deinit( &before_ram ); +} +END_TEST + +START_TEST( test_cpu_6502_ldx ) +{ + cpu_6502_t before_cpu; + memory_t before_ram; + + cpu_6502_reset( &cpu ); + memory_reset( &rom ); + memory_reset( &ram ); + + memset( code, 0, ROM_SIZE ); + code[0] = 0xa2; // LDX immediate + code[1] = 0x01; // #$1 + codesize = 2; + memory_set( &rom, 0x00, code, codesize ); + + cpu.X = 0xff; + + memcpy( &before_cpu, &cpu, sizeof( cpu ) ); + memory_copy( &before_ram, &ram ); + + cpu_6502_run( &cpu, 1 ); + + fprintf( stderr, "state before:\n" ); + cpu_6502_print_debug( &before_cpu ); + fprintf( stderr, "state after:\n" ); + cpu_6502_print_debug( &cpu ); + + 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_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, 0x01 ); + ck_assert_int_eq( cpu.Y, before_cpu.Y ); + ck_assert_mem_eq( ram.cell, before_ram.cell, ram.size ); + + memory_deinit( &before_ram ); } END_TEST Suite *make_cpu_6502_testsuite( void ) { Suite *suite; + TCase *tc; suite = suite_create( "6502 CPU tests" ); - TCase *tc_nop = tcase_create( "NOP" ); - tcase_add_checked_fixture( tc_nop, setup, teardown); - tcase_add_test( tc_nop, test_cpu_6502_nop ); - suite_add_tcase( suite, tc_nop ); - - TCase *tc_txs = tcase_create( "TXS" ); - tcase_add_checked_fixture( tc_txs, setup, teardown); - tcase_add_test( tc_txs, test_cpu_6502_txs ); - suite_add_tcase( suite, tc_txs ); + tc = tcase_create( "NOP" ); + tcase_add_unchecked_fixture( tc, setup, teardown); + tcase_add_test( tc, test_cpu_6502_nop ); + suite_add_tcase( suite, tc ); + + tc = tcase_create( "TXS" ); + tcase_add_unchecked_fixture( tc, setup, teardown); + tcase_add_test( tc, test_cpu_6502_txs ); + suite_add_tcase( suite, tc ); + + tc = tcase_create( "LDX" ); + tcase_add_unchecked_fixture( tc, setup, teardown); + tcase_add_test( tc, test_cpu_6502_ldx ); + suite_add_tcase( suite, tc ); return suite; } -- cgit v1.2.3-54-g00ecf