From 1269d11d15f1014b7ac87fc2bb2c76367404e16c Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 10 Dec 2020 19:50:39 +0100 Subject: some more unit testing --- emu/6502.c | 8 ++-- emu/6502.h | 8 ++++ emu/CMakeLists.txt | 8 ++-- emu/emul.c | 2 +- emu/memory.c | 12 +++++- emu/memory.h | 2 + emu/tests/CMakeLists.txt | 6 ++- emu/tests/test_cpu_6502.c | 100 +++++++++++++++++++++++++++++++++++++++++++--- 8 files changed, 130 insertions(+), 16 deletions(-) (limited to 'emu') diff --git a/emu/6502.c b/emu/6502.c index c52373f..139b6f6 100644 --- a/emu/6502.c +++ b/emu/6502.c @@ -2,7 +2,6 @@ #include "memory.h" #include -#include static const uint16_t reset_vector = 0xFFFC; static const uint16_t ZP_base = 0x0; @@ -13,6 +12,7 @@ void cpu_6502_init( cpu_6502_t *cpu, bus_t *bus, bool initialize ) cpu->bus = bus; cpu->debug_flags = 0; cpu->steps = 0; + cpu->error_state = ERROR_STATE_OK; if( initialize ) { cpu->PC = 0x0000; @@ -88,11 +88,11 @@ void cpu_6502_write_word( cpu_6502_t *cpu, uint16_t addr, uint16_t data ) void cpu_6502_run( cpu_6502_t *cpu, int steps ) { if( steps != -1 ) { - for( int i = 0; i < steps; i++ ) { + for( int i = 1; i <= steps && cpu->error_state == ERROR_STATE_OK; i++ ) { cpu_6502_step( cpu ); } } else { - while( true ) { + while( cpu->error_state == ERROR_STATE_OK ) { cpu_6502_step( cpu ); } } @@ -429,7 +429,7 @@ void cpu_6502_step( cpu_6502_t *cpu ) default: fprintf( stderr, "ERROR: Illegal opcode %02X at PC %04X\n", opcode, cpu->PC ); - exit( EXIT_FAILURE ); + cpu->error_state |= ERROR_STATE_ILLEGAL_OPCODE; } cpu->steps++; diff --git a/emu/6502.h b/emu/6502.h index 1880c90..c3143e7 100644 --- a/emu/6502.h +++ b/emu/6502.h @@ -20,6 +20,8 @@ typedef struct int debug_flags; int steps; + + int error_state; } cpu_6502_t; // debug flags @@ -29,6 +31,12 @@ enum { DEBUG_STACK = 0x04 }; +// error state +enum { + ERROR_STATE_OK = 0x00, + ERROR_STATE_ILLEGAL_OPCODE = 0x01 +}; + // processor state bits enum { PS_N = 0x80, diff --git a/emu/CMakeLists.txt b/emu/CMakeLists.txt index 535802a..6e13d00 100644 --- a/emu/CMakeLists.txt +++ b/emu/CMakeLists.txt @@ -27,7 +27,6 @@ set(SRC memory.c 7seg.c emul.c - emu.c ) ADD_GENGETOPT_FILES(SRC options.ggo) @@ -40,8 +39,11 @@ PKG_SEARCH_MODULE(CHECK REQUIRED check) include_directories(${SDL2_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS}) -add_executable(emu ${SRC}) -target_link_libraries(emu ${SDL2_LIBRARIES} ${SDL2_GFX_LIBRARIES}) +add_library(emulib STATIC ${SRC}) + +add_executable(emu emu.c) +target_link_libraries(emu ${SDL2_LIBRARIES} ${SDL2_GFX_LIBRARIES} emulib) enable_testing() add_subdirectory(tests) +add_custom_target(report DEPENDS tests/test.html) diff --git a/emu/emul.c b/emu/emul.c index 4d2c3f1..ff3ac38 100644 --- a/emu/emul.c +++ b/emu/emul.c @@ -97,7 +97,7 @@ void emul_run( emul_t *emul, int nof_steps ) print_help( ); } - while( !done ) { + while( !done && emul->cpu->error_state == ERROR_STATE_OK ) { uint32_t frame_start = SDL_GetTicks( ); SDL_PollEvent( &event ); diff --git a/emu/memory.c b/emu/memory.c index 620261b..c73c668 100644 --- a/emu/memory.c +++ b/emu/memory.c @@ -20,7 +20,7 @@ void memory_init( memory_t *memory, memory_type_t type, uint16_t addr, uint16_t memory->size = size; memory->cell = malloc( memory->size ); if( initialize ) { - memset( memory->cell, 0, memory->size ); + memory_reset( memory ); } memory->base.vtable = (device_vtable_t *)&memory_vtable; @@ -43,6 +43,16 @@ void memory_load( memory_t *memory, const char *filename ) } } +void memory_set( memory_t *memory, uint16_t addr, uint8_t *buf, int bufsize ) +{ + memcpy( &memory->cell[addr], buf, bufsize ); +} + +void memory_reset( memory_t *memory ) +{ + memset( memory->cell, 0, memory->size ); +} + uint8_t memory_read( void *obj, uint16_t addr ) { memory_t *memory = (memory_t *)obj; diff --git a/emu/memory.h b/emu/memory.h index 00e0de6..3a15bfe 100644 --- a/emu/memory.h +++ b/emu/memory.h @@ -23,6 +23,8 @@ typedef struct memory_t void memory_init( memory_t *memory, memory_type_t type, uint16_t addr, uint16_t size, bool initialize ); 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 ); uint8_t memory_read( void *obj, uint16_t addr ); void memory_write( void *obj, uint16_t addr, uint8_t data ); diff --git a/emu/tests/CMakeLists.txt b/emu/tests/CMakeLists.txt index 5011371..88d2e97 100644 --- a/emu/tests/CMakeLists.txt +++ b/emu/tests/CMakeLists.txt @@ -1,4 +1,8 @@ add_executable(test_cpu_6502 test_cpu_6502.c) -target_link_libraries(test_cpu_6502 ${CHECK_LIBRARIES} pthread) +target_link_libraries(test_cpu_6502 ${CHECK_LIBRARIES} pthread emulib) + +include_directories(${CMAKE_SOURCE_DIR}) add_test(NAME test_cpu_6502 COMMAND test_cpu_6502 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests) + +add_custom_target(test.html DEPENDS test.xml COMMAND xsltproc check_unittest.xslt test.xml > test.html DEPENDS test.xml) diff --git a/emu/tests/test_cpu_6502.c b/emu/tests/test_cpu_6502.c index 0eb6a2b..6f53ff0 100644 --- a/emu/tests/test_cpu_6502.c +++ b/emu/tests/test_cpu_6502.c @@ -2,31 +2,119 @@ #include #include +#include "6502.h" +#include "bus.h" +#include "memory.h" + +enum { + ROM_START = 0xf800, + ROM_END = 0xffff, + ROM_SIZE = 2048, + + RAM_START = 0x0000, + RAM_END = 0x01ff, + RAM_SIZE = 512 +}; + +static cpu_6502_t cpu; +static bus_t bus; +static memory_t rom; +static memory_t ram; +static uint8_t code[ROM_SIZE]; +static int codesize; + void setup( void ) { + bus_init( &bus ); + + cpu_6502_init( &cpu, &bus, true ); + cpu.debug_flags |= DEBUG_STATUS | DEBUG_STACK | DEBUG_ZERO_PAGE; + + memory_init( &rom, MEMORY_ROM, ROM_START, ROM_SIZE, true ); + bus_register( &bus, &rom.base, ROM_START, ROM_END ); + + memory_init( &ram, MEMORY_RAM, RAM_START, RAM_SIZE, true ); + bus_register( &bus, &ram.base, RAM_START, RAM_END ); + + // install code start vector + code[0] = ROM_START & 0x00ff; + code[1] = ( ROM_START & 0xff00 ) >> 8; + codesize = 2; + memory_set( &rom, 0x07fc, code, codesize ); } void teardown( void ) { + bus_deinit( &bus ); } START_TEST( test_cpu_6502_nop ) { + cpu_6502_t before_cpu; + + cpu_6502_reset( &cpu ); + memory_reset( &rom ); + memory_reset( &ram ); + + code[0] = 0xea; // NOP + codesize = 1; + memory_set( &rom, 0x00, code, codesize ); + + memcpy( &before_cpu, &cpu, sizeof( cpu ) ); + cpu_6502_run( &cpu, 1 ); + + 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, 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 ); +} +END_TEST + +START_TEST( test_cpu_6502_txs ) +{ + cpu_6502_t before_cpu; + + cpu_6502_reset( &cpu ); + memory_reset( &rom ); + memory_reset( &ram ); + + code[0] = 0x9a; // TXS + codesize = 1; + memory_set( &rom, 0x00, code, codesize ); + + cpu.X = 0xff; + + memcpy( &before_cpu, &cpu, sizeof( cpu ) ); + cpu_6502_run( &cpu, 1 ); + + 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, cpu.X ); + ck_assert_int_eq( cpu.PS, before_cpu.PS ); + 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 ); } END_TEST Suite *make_cpu_6502_testsuite( void ) { Suite *suite; - TCase *tc_opcodes; suite = suite_create( "6502 CPU tests" ); - tc_opcodes = tcase_create( "test opcodes" ); - - tcase_add_test( tc_opcodes, test_cpu_6502_nop ); - - suite_add_tcase( suite, tc_opcodes ); + 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 ); return suite; } -- cgit v1.2.3-54-g00ecf