summaryrefslogtreecommitdiff
path: root/emu
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-12-10 19:50:39 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2020-12-10 19:50:39 +0100
commit1269d11d15f1014b7ac87fc2bb2c76367404e16c (patch)
treed8d4595811b279d2e7d5ccef32f55ba5cbcba585 /emu
parent84e25eb07749636b48deb802d673f44841c55d91 (diff)
download6502-1269d11d15f1014b7ac87fc2bb2c76367404e16c.tar.gz
6502-1269d11d15f1014b7ac87fc2bb2c76367404e16c.tar.bz2
some more unit testing
Diffstat (limited to 'emu')
-rw-r--r--emu/6502.c8
-rw-r--r--emu/6502.h8
-rw-r--r--emu/CMakeLists.txt8
-rw-r--r--emu/emul.c2
-rw-r--r--emu/memory.c12
-rw-r--r--emu/memory.h2
-rw-r--r--emu/tests/CMakeLists.txt6
-rw-r--r--emu/tests/test_cpu_6502.c100
8 files changed, 130 insertions, 16 deletions
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 <stdio.h>
-#include <stdlib.h>
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 <stdint.h>
#include <check.h>
+#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;
}