Improved "stop events" by using an event ID for every byte of memory.
authorAndreas Eversberg <jolly@eversberg.eu>
Sat, 10 Mar 2018 21:16:16 +0000 (22:16 +0100)
committerAndreas Eversberg <jolly@eversberg.eu>
Sun, 25 Mar 2018 12:25:15 +0000 (14:25 +0200)
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
src/libcpu/execute.h
src/mercenary/main.c

index 9d3180e..a173d2c 100644 (file)
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
+#include <string.h>
 #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);
        }
index 2b84421..3ca7497 100644 (file)
@@ -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);
 
index d831d26..ef7ce5d 100644 (file)
@@ -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)