summaryrefslogtreecommitdiff
path: root/emu
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-12-12 20:14:45 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2020-12-12 20:14:45 +0100
commit8dde478cfc2174f198290be40a633a4c9c9db833 (patch)
treef3ebae298dc285fd407093efbf774a684f520867 /emu
parent1269d11d15f1014b7ac87fc2bb2c76367404e16c (diff)
download6502-8dde478cfc2174f198290be40a633a4c9c9db833.tar.gz
6502-8dde478cfc2174f198290be40a633a4c9c9db833.tar.bz2
some more testing
Diffstat (limited to 'emu')
-rw-r--r--emu/6502.c63
-rw-r--r--emu/6502.h12
-rw-r--r--emu/device.c7
-rw-r--r--emu/device.h1
-rw-r--r--emu/memory.c9
-rw-r--r--emu/memory.h1
-rw-r--r--emu/tests/check_unittest.xslt2
-rw-r--r--emu/tests/test_cpu_6502.c90
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
</xsl:template>
<xsl:template match="c:test[@result='success']">
- <tr bgcolor="green"><xsl:apply-templates/></tr>
+ <tr bgcolor="#90EE90"><xsl:apply-templates/></tr>
</xsl:template>
<xsl:template match="c:test[@result='error']">
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;
}