From dd4174bb32973d1212235dc8e262c23013b88912 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Mon, 28 Dec 2020 16:10:40 +0100 Subject: introduced cycles --- LINKS | 1 + emu/6502.c | 52 ++++++++++++++++++++++++++++------ emu/6502.h | 4 ++- emu/emul.c | 6 ++-- emu/memory.c | 2 +- emu/tests/test_cpu_6502.c | 72 +++++++++++++++++++++++------------------------ 6 files changed, 88 insertions(+), 49 deletions(-) diff --git a/LINKS b/LINKS index f84bea6..36213cc 100644 --- a/LINKS +++ b/LINKS @@ -139,6 +139,7 @@ https://www.pagetable.com/?p=410 https://github.com/Klaus2m5/6502_65C02_functional_tests http://nparker.llx.com/a2/opcodes.html https://blog.scottlogic.com/2020/08/26/codegen-6502-webassembly.html +http://www.righto.com/2012/12/the-6502-overflow-flag-explained.html testing: http://www.ucunit.org/_related__sites.html diff --git a/emu/6502.c b/emu/6502.c index cab72b3..53af7a0 100644 --- a/emu/6502.c +++ b/emu/6502.c @@ -12,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->cycles = 0; cpu->error_state = ERROR_STATE_OK; if( initialize ) { @@ -85,7 +86,7 @@ void cpu_6502_write_word( cpu_6502_t *cpu, uint16_t addr, uint16_t data ) cpu->bus->base.vtable->write( cpu->bus, addr + 1, ( data && 0x00FF ) ); } -void cpu_6502_run( cpu_6502_t *cpu, int steps ) +void cpu_6502_run_steps( cpu_6502_t *cpu, int steps ) { if( steps != -1 ) { for( int i = 1; i <= steps && cpu->error_state == ERROR_STATE_OK; i++ ) { @@ -98,6 +99,20 @@ void cpu_6502_run( cpu_6502_t *cpu, int steps ) } } +void cpu_6502_run_cycles( cpu_6502_t *cpu, int cycles ) +{ + if( cycles != -1 ) { + int start_cycles = cpu->cycles; + while( cpu->cycles < start_cycles + cycles && cpu->error_state == ERROR_STATE_OK ) { + cpu_6502_step( cpu ); + } + } else { + while( cpu->error_state == ERROR_STATE_OK ) { + cpu_6502_step( cpu ); + } + } +} + static void handle_zero( cpu_6502_t *cpu, uint8_t x ) { if( x == 0 ) { @@ -151,8 +166,28 @@ bool cpu_6502_is_carry( cpu_6502_t *cpu ) return cpu->PS & PS_C; } +static const int cycles[NOF_OPCODES] = { + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 2 */ 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + /* 3 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + /* 5 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 6 */ 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 7 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 8 */ 0, 0, 0, 0, 0, 0, 3, 0, 2, 0, 0, 0, 0, 0, 4, 0, + /* 9 */ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + /* A */ 2, 0, 2, 0, 3, 3, 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, + /* B */ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* C */ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, + /* D */ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* E */ 3, 0, 0, 0, 0, 0, 5, 0, 0, 2, 2, 0, 0, 0, 0, 0, + /* F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + static const char mnemonic[NOF_OPCODES][MAX_MENMONIC_LENGTH] = { - /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ /* 0 */ "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", /* 1 */ "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", /* 2 */ "JSR", "???", "???", "???", "???", "???", "???", "???", "???", "???", "ROL", "???", "???", "???", "???", "???", @@ -169,6 +204,7 @@ static const char mnemonic[NOF_OPCODES][MAX_MENMONIC_LENGTH] = { /* D */ "BNE", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", /* E */ "CPX", "???", "???", "???", "???", "???", "INC", "???", "???", "SBC", "NOP", "???", "???", "???", "???", "???", /* F */ "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???", "???" +}; /* "BRK", "ORA", "" , "", "TSB", "ORA", "ASL", "RMB0", "PHP", "ORA", "ASL", "" , "TSB", "ORA", "ASL", "BBR0", @@ -188,7 +224,6 @@ static const char mnemonic[NOF_OPCODES][MAX_MENMONIC_LENGTH] = { "CPX", "SBC", "" , "", "CPX", "SBC", "INC", "SMB6", "INX", "SBC", "NOP", "" , "CPX", "SBC", "INC", "BBS6", "BEQ", "SBC", "SBC", "", "" , "SBC", "INC", "SMB7", "SED", "SBC", "PLX", "" , "" , "SBC", "INC", "BBS7" */ -}; void cpu_6502_get_opcode_mnemonic( cpu_6502_t *cpu, char *buf, int buflen, uint16_t addr ) { @@ -218,7 +253,7 @@ void cpu_6502_print_state( cpu_6502_t *cpu, uint16_t addr ) cpu_6502_get_opcode_mnemonic( cpu, opcode_str, MAX_OPCODE_MNEMONIC_STRING_LENGTH, 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", + fprintf( stderr, "PC: %04X SP: 01%02X PS: %02X %c%c-%c%c%c%c%c A: %02X X: %02X Y: %02X steps: %d cycles: %d OP: %s\n", cpu->PC, cpu->SP, cpu->PS, cpu_6502_is_negative( cpu ) ? 'N' : 'n', cpu_6502_is_overflow( cpu ) ? 'V' : 'v', @@ -228,7 +263,7 @@ void cpu_6502_print_state( cpu_6502_t *cpu, uint16_t addr ) cpu_6502_is_zero( cpu ) ? 'Z' : 'z', cpu_6502_is_carry( cpu ) ? 'C' : 'c', cpu->A, cpu->X, cpu->Y, cpu->steps, - opcode_str ); + cpu->cycles, opcode_str ); } static void update_negative_and_sign( cpu_6502_t *cpu, uint8_t x ) @@ -372,12 +407,12 @@ 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 ) ? 1 : 0 ); + tmp = cpu->A - operand8 - ( cpu_6502_is_carry( cpu ) ? 0 : 1 ); update_negative_and_sign( cpu, tmp ); if( tmp & 0xFF00 ) { - cpu->PS |= PS_C; - } else { cpu->PS &= ~PS_C; + } else { + cpu->PS |= PS_C; } if( ( ( cpu->A ^ tmp ) & 0x80 ) && ( ( cpu->A ^ operand8 ) & 0x80 ) ) { cpu->PS |= PS_V; @@ -438,4 +473,5 @@ void cpu_6502_step( cpu_6502_t *cpu ) } cpu->steps++; + cpu->cycles += cycles[opcode]; } diff --git a/emu/6502.h b/emu/6502.h index 9dc8614..c462fcc 100644 --- a/emu/6502.h +++ b/emu/6502.h @@ -20,6 +20,7 @@ typedef struct int debug_flags; int steps; + int cycles; int error_state; } cpu_6502_t; @@ -92,7 +93,8 @@ 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_run_steps( cpu_6502_t *cpu, int steps ); +void cpu_6502_run_cycles( cpu_6502_t *cpu, int cycles ); 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 ); diff --git a/emu/emul.c b/emu/emul.c index 53d5ed2..3ee60c0 100644 --- a/emu/emul.c +++ b/emu/emul.c @@ -118,7 +118,7 @@ void emul_run( emul_t *emul, int nof_steps ) emul->paused = true; break; case SDLK_s: - cpu_6502_run( emul->cpu, 1 ); + cpu_6502_run_steps( emul->cpu, 1 ); break; case SDLK_EQUALS: case SDLK_KP_EQUALS: @@ -147,7 +147,7 @@ void emul_run( emul_t *emul, int nof_steps ) } if( !emul->paused ) { - cpu_6502_run( emul->cpu, emul->speed / DISPLAY_FPS ); + cpu_6502_run_cycles( emul->cpu, emul->speed / DISPLAY_FPS ); } SDL_RenderCopy( emul->renderer, emul->background_texture, NULL, NULL ); @@ -171,7 +171,7 @@ void emul_run( emul_t *emul, int nof_steps ) } } } else { - cpu_6502_run( emul->cpu, nof_steps ); + cpu_6502_run_steps( emul->cpu, nof_steps ); } #else cpu_6502_run( emul->cpu, nof_steps ); diff --git a/emu/memory.c b/emu/memory.c index 3ab0694..4ddd8c3 100644 --- a/emu/memory.c +++ b/emu/memory.c @@ -45,7 +45,7 @@ void memory_load( memory_t *memory, const char *filename ) } fread( &memory->cell[0], memory->size, 1, f ); fclose( f ); - fprintf( stderr, "INFO: Loaded firware from '%s' of size %d starting on address %04X\n", + fprintf( stderr, "INFO: Loaded firmware from '%s' of size %d starting on address %04X\n", filename, memory->size, memory->addr ); } else { fprintf( stderr, "ERROR: Cannot load firmware into RAM at address %04X\n", memory->addr ); diff --git a/emu/tests/test_cpu_6502.c b/emu/tests/test_cpu_6502.c index 86d1115..37394ab 100644 --- a/emu/tests/test_cpu_6502.c +++ b/emu/tests/test_cpu_6502.c @@ -100,7 +100,7 @@ START_TEST( test_cpu_6502_nop ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -129,7 +129,7 @@ START_TEST( test_cpu_6502_txs ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -158,7 +158,7 @@ START_TEST( test_cpu_6502_lda_flags_positive ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -185,7 +185,7 @@ START_TEST( test_cpu_6502_lda_flags_negative ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -214,7 +214,7 @@ START_TEST( test_cpu_6502_lda_flags_zero ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -245,7 +245,7 @@ START_TEST( test_cpu_6502_ldy_flags_positive ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -272,7 +272,7 @@ START_TEST( test_cpu_6502_ldy_flags_negative ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -301,7 +301,7 @@ START_TEST( test_cpu_6502_ldy_flags_zero ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -332,7 +332,7 @@ START_TEST( test_cpu_6502_ldx_flags_positive ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -359,7 +359,7 @@ START_TEST( test_cpu_6502_ldx_flags_negative ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -388,7 +388,7 @@ START_TEST( test_cpu_6502_ldx_flags_zero ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -419,7 +419,7 @@ START_TEST( test_cpu_6502_stx_addr_zero ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -448,7 +448,7 @@ START_TEST( test_cpu_6502_stx_addr_abs ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -479,7 +479,7 @@ START_TEST( test_cpu_6502_inc_flags_positive ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -510,7 +510,7 @@ START_TEST( test_cpu_6502_inc_flags_negative ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -541,7 +541,7 @@ START_TEST( test_cpu_6502_inc_flags_zero ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -574,7 +574,7 @@ START_TEST( test_cpu_6502_inx_flags_positive ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -603,7 +603,7 @@ START_TEST( test_cpu_6502_inx_flags_negative ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -632,7 +632,7 @@ START_TEST( test_cpu_6502_inx_flags_zero ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -663,7 +663,7 @@ START_TEST( test_cpu_6502_dex_flags_positive ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -692,7 +692,7 @@ START_TEST( test_cpu_6502_dex_flags_negative ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -721,7 +721,7 @@ START_TEST( test_cpu_6502_dex_flags_zero ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -752,7 +752,7 @@ START_TEST( test_cpu_6502_dey_flags_positive ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -781,7 +781,7 @@ START_TEST( test_cpu_6502_dey_flags_negative ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -810,7 +810,7 @@ START_TEST( test_cpu_6502_dey_flags_zero ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -842,7 +842,7 @@ START_TEST( test_cpu_6502_rol_flags_accumulator_carry ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -874,7 +874,7 @@ START_TEST( test_cpu_6502_cpx_flags_equals ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -904,7 +904,7 @@ START_TEST( test_cpu_6502_cpx_flags_less ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -934,7 +934,7 @@ START_TEST( test_cpu_6502_cpx_flags_greater ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -966,7 +966,7 @@ START_TEST( test_cpu_6502_bcc_carry_clear ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -993,7 +993,7 @@ START_TEST( test_cpu_6502_bcc_carry_set ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -1022,7 +1022,7 @@ START_TEST( test_cpu_6502_bne_zero_clear ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -1049,7 +1049,7 @@ START_TEST( test_cpu_6502_bne_zero_set ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -1076,7 +1076,7 @@ START_TEST( test_cpu_6502_jmp_abs ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -1105,7 +1105,7 @@ START_TEST( test_cpu_6502_jsr_abs ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST @@ -1138,7 +1138,7 @@ START_TEST( test_cpu_6502_rts ) COPY_CPU_TEST - cpu_6502_run( &cpu, 1 ); + cpu_6502_run_steps( &cpu, 1 ); PRINT_CPU_TEST -- cgit v1.2.3-54-g00ecf