From 093cce0a28623b6dcf3e83325d2c36859d5d94fc Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sat, 10 Mar 2018 22:16:16 +0100 Subject: [PATCH] Improved "stop events" by using an event ID for every byte of memory. Instead of hunting the list of all events for every CPU instruction, we just check if the event ID of the current PC is set. --- src/libcpu/execute.c | 36 +++++++++++++++++++++++++----------- src/libcpu/execute.h | 6 +++--- src/mercenary/main.c | 16 ++++++++++++---- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/libcpu/execute.c b/src/libcpu/execute.c index 9d3180e..a173d2c 100644 --- a/src/libcpu/execute.c +++ b/src/libcpu/execute.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "../libsdl/print.h" #include "execute.h" #include "m68k.h" @@ -31,6 +32,7 @@ #define IOBASE 0x00dff000 static uint8_t *memory = NULL; +static uint8_t *stop_event = NULL; static uint32_t memory_size = 0; static uint16_t *chipreg = NULL; static uint16_t (*io_read)(uint32_t address) = NULL; @@ -130,14 +132,27 @@ void m68k_write_memory_32(unsigned int address, unsigned int value) memory[address + 3] = value; } -void execute_init(int32_t _memory_size, uint8_t *_memory, uint16_t *_chipreg, uint16_t (*_io_read)(uint32_t address), void (*_io_write)(uint32_t address, uint16_t value)) +void execute_init(int32_t _memory_size, uint8_t *_memory, uint8_t *_stop_event, uint16_t *_chipreg, uint16_t (*_io_read)(uint32_t address), void (*_io_write)(uint32_t address, uint16_t value), const struct cpu_stop stop_at[]) { + int i; + memory_size = _memory_size; memory = _memory; + stop_event = _stop_event; chipreg = _chipreg; io_read = _io_read; io_write = _io_write; + /* flag where the cpu shall stop at */ + memset(stop_event, 0, _memory_size); + for (i = 0; stop_at[i].event; i++) { + if (stop_at[i].pc >= memory_size) { + fprintf(stderr, "stop-event at PC=%x is out of memory=%x\n", stop_at[i].pc, memory_size); + exit(0); + } + stop_event[stop_at[i].pc] = stop_at[i].event; + } + /* init CPU */ m68k_init(); m68k_set_cpu_type(M68K_CPU_TYPE_68000); @@ -148,11 +163,10 @@ void reset_cpu(void) m68k_pulse_reset(); } -int execute_cpu(int irq, const struct cpu_stop stop_at[], int *event) +int execute_cpu(int irq, int *event) { int cycle_count = 0; int instruction_count = 0; - int i; uint32_t save_pc; if (irq) { @@ -182,14 +196,14 @@ int execute_cpu(int irq, const struct cpu_stop stop_at[], int *event) break; } - for (i = 0; stop_at[i].event; i++) { - if (REG_PC == stop_at[i].pc) { -#ifdef DEBUG_CPU - print_error("execution to address 0x%06x took %d opcodes\n", REG_PC, instruction_count); -#endif - *event = stop_at[i].event; - return cycle_count; - } + /* stop execution if there is an event */ + if (REG_PC >= memory_size) { + print_error("CPU execution reaches PC=%x that is out of memory=%x\n", REG_PC, memory_size); + exit(0); + } + if (stop_event[REG_PC]) { + *event = stop_event[REG_PC]; + return cycle_count; } } while (42); } diff --git a/src/libcpu/execute.h b/src/libcpu/execute.h index 2b84421..3ca7497 100644 --- a/src/libcpu/execute.h +++ b/src/libcpu/execute.h @@ -1,10 +1,10 @@ struct cpu_stop { uint32_t pc; - int event; + uint8_t event; }; -void execute_init(int32_t _memory_size, uint8_t *_memory, uint16_t *_chipreg, uint16_t (*io_read)(uint32_t address), void (*io_write)(uint32_t address, uint16_t value)); +void execute_init(int32_t _memory_size, uint8_t *_memory, uint8_t *_stop_event, uint16_t *_chipreg, uint16_t (*_io_read)(uint32_t address), void (*_io_write)(uint32_t address, uint16_t value), const struct cpu_stop stop_at[]); void reset_cpu(void); -int execute_cpu(int irq, const struct cpu_stop stop_at[], int *event); +int execute_cpu(int irq, int *event); diff --git a/src/mercenary/main.c b/src/mercenary/main.c index d831d26..ef7ce5d 100644 --- a/src/mercenary/main.c +++ b/src/mercenary/main.c @@ -63,6 +63,7 @@ static int config_debug_opengl = 0; #define IOSIZE 0x1000 /* bytes in io space */ #define MEMORY_SIZE 0x80000 static uint8_t *memory = NULL; +static uint8_t *stop_event = NULL; static uint8_t *image = NULL; #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 200 @@ -212,7 +213,7 @@ static void main_loop(void) /* execute until the rendered image is ready (wait for VBL) */ cycle_count = 0; do { - cycle_count += execute_cpu(0, mercenary_stop_at, &event); + cycle_count += execute_cpu(0, &event); /* handle special events */ if (event != STOP_AT_WAIT_VBL) special_event(event); @@ -253,8 +254,8 @@ static void main_loop(void) last_time = current_time - 1000 * SOUND_CHUNKS / IRQ_RATE; } while (diff > 1000 / IRQ_RATE) { - execute_cpu(3, NULL, NULL); - execute_cpu(4, NULL, NULL); + execute_cpu(3, NULL); + execute_cpu(4, NULL); had_first_irq = 1; /* render benson without game view * because we only got benson refreshed during VBL IRQ @@ -664,6 +665,11 @@ int main(int argc, char *argv[]) print_error("Failed to allocate cpu's memory\n"); goto done; } + stop_event = calloc(MEMORY_SIZE, 1); + if (!stop_event) { + print_error("Failed to allocate cpu's stop_event memory\n"); + goto done; + } chipreg = calloc(IOSIZE, 1); if (!chipreg) { print_error("Failed to allocate chip register\n"); @@ -671,7 +677,7 @@ int main(int argc, char *argv[]) } /* init cpu code */ - execute_init(MEMORY_SIZE, memory, chipreg, io_read, io_write); + execute_init(MEMORY_SIZE, memory, stop_event, chipreg, io_read, io_write, mercenary_stop_at); /* init disk emulation */ disk_init(disk_read, disk_write); @@ -718,6 +724,8 @@ done: if (chipreg) free(chipreg); + if (stop_event) + free(stop_event); if (memory) free(memory); if (sound_buffer) -- 2.13.6