From 274c99f98bd9a8c53ab988364592d676ecf69693 Mon Sep 17 00:00:00 2001 From: bruno Date: Sat, 22 Feb 2025 16:15:05 +0100 Subject: [PATCH] Add non multithread mode --- assembler/assembler.c | 17 ++++++--- assembler/assembler.h | 2 +- main.c | 87 +++++++++++++++++++++++++++++------------- peripherals/switches.c | 2 +- 4 files changed, 74 insertions(+), 34 deletions(-) diff --git a/assembler/assembler.c b/assembler/assembler.c index 11aa99b..e746abd 100644 --- a/assembler/assembler.c +++ b/assembler/assembler.c @@ -210,9 +210,9 @@ int resolveMOV(const char *dest, const char *src) { } } -int resolveALU(int baseOpcode, const char *src) { +int resolveALU(int baseOpcode, const char *src, const char *dest) { // baseOpcode is one of our special negative values for ADD, SUB, etc. - if (src[0] == 'R' || src[0] == 'r') { + if (dest[0] == 'R' || dest[0] == 'r') { switch (baseOpcode) { case -3: return ADD_RN_RM; @@ -230,6 +230,11 @@ int resolveALU(int baseOpcode, const char *src) { return OR_RN_RM; case -10: return XOR_RN_RM; + default: + return -1; + } + } else if (src[0] == 'r' || src[0] == 'R' && baseOpcode < -11) { + switch (baseOpcode) { case -12: return INC_RN; case -13: @@ -467,7 +472,7 @@ uint32_t completePass(const char *source, CPU *cpu, bool erase) { fprintf(stderr, "Error: %s requires one operand.\n", mnemonic); return 1; } - int resolvedOpcode = resolveALU(baseOpcode, operand1); + int resolvedOpcode = resolveALU(baseOpcode, operand1, operand2); cpu->memory[addr++] = resolvedOpcode; if (operand1[0] == 'R' || operand1[0] == 'r') { int reg = parseRegister(operand1); @@ -491,7 +496,7 @@ uint32_t completePass(const char *source, CPU *cpu, bool erase) { fprintf(stderr, "Error: %s requires two operands.\n", mnemonic); return 1; } - int resolvedOpcode = resolveALU(baseOpcode, operand1); + int resolvedOpcode = resolveALU(baseOpcode, operand1, operand2); cpu->memory[addr++] = resolvedOpcode; int regDest = parseRegister(operand1); cpu->memory[addr++] = regDest; @@ -509,7 +514,7 @@ uint32_t completePass(const char *source, CPU *cpu, bool erase) { fprintf(stderr, "Error: JMP requires one operand.\n"); return 1; } - int resolvedOpcode = resolveALU(baseOpcode, operand1); + int resolvedOpcode = resolveALU(baseOpcode, operand1, operand2); cpu->memory[addr++] = resolvedOpcode; if (operand1[0] == '+' || operand1[0] == '-') { // Relative jump: one-byte offset. @@ -529,7 +534,7 @@ uint32_t completePass(const char *source, CPU *cpu, bool erase) { fprintf(stderr, "Error: %s requires three operands.\n", mnemonic); return 1; } - int resolvedOpcode = resolveALU(baseOpcode, operand1); + int resolvedOpcode = resolveALU(baseOpcode, operand1, operand2); cpu->memory[addr++] = resolvedOpcode; // Encode the source operand (register or memory). if (operand1[0] == 'R' || operand1[0] == 'r') { diff --git a/assembler/assembler.h b/assembler/assembler.h index efa45d9..a959d67 100644 --- a/assembler/assembler.h +++ b/assembler/assembler.h @@ -70,7 +70,7 @@ int getOpcode(char *mnemonic); // int resolveMOV(const char *dest, const char *src); -int resolveALU(int baseOpcode, const char *src); +int resolveALU(int baseOpcode, const char *src, const char *dest); // // The first pass scans the assembly source file to record all labels and their addresses. diff --git a/main.c b/main.c index 30df78d..4cec83a 100644 --- a/main.c +++ b/main.c @@ -28,6 +28,8 @@ SDL_Renderer *renderer = NULL; #define smallFont fonts[1] #define smallerFont fonts[2] +//#define CPU_THREADED + #define fontCount 3 BitmapFont fonts[fontCount]; @@ -49,8 +51,10 @@ TextEditor editors[editorCount]; unsigned long frames = 0; bool cursor = true; +#ifdef CPU_THREADED pthread_t cpu_thread; pthread_mutex_t cpu_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif void msleep(unsigned int milliseconds) { struct timespec ts; @@ -59,32 +63,54 @@ void msleep(unsigned int milliseconds) { nanosleep(&ts, NULL); } -void *cpu_loop(void *arg) { - uint64_t last_tick = SDL_GetTicks64(); - while (running) { - pthread_mutex_lock(&cpu_mutex); +static uint64_t last_tick = 0; - if (!(cpu.mode & (CPU_MODE_PAUSED | CPU_MODE_HALTED | CPU_MODE_ERROR))) { - step(&cpu); - } else { - pthread_mutex_unlock(&cpu_mutex); - msleep(10); - } +// This function executes one iteration of the CPU loop (non-blocking) +void cpu_step(void) { + if (last_tick == 0) { + last_tick = SDL_GetTicks64(); + } - if (cpu.mode & CPU_MODE_SECOND) { - pthread_mutex_unlock(&cpu_mutex); - msleep(1000); - continue; - } else if (cpu.mode & CPU_MODE_FRAME) { - uint64_t frame_duration = SDL_GetTicks64() - last_tick; - if (frame_duration < delayNeeded) { - pthread_mutex_unlock(&cpu_mutex); - msleep(delayNeeded - frame_duration); - continue; - } - last_tick = SDL_GetTicks64(); - } +#ifdef CPU_THREADED + pthread_mutex_lock(&cpu_mutex); +#endif + + if (!(cpu.mode & (CPU_MODE_PAUSED | CPU_MODE_HALTED | CPU_MODE_ERROR))) { + step(&cpu); + } else { +#ifdef CPU_THREADED pthread_mutex_unlock(&cpu_mutex); +#endif + return; + } + + if (cpu.mode & CPU_MODE_SECOND) { +#ifdef CPU_THREADED + pthread_mutex_unlock(&cpu_mutex); +#endif + msleep(1000); + return; + } else if (cpu.mode & CPU_MODE_FRAME) { + uint64_t frame_duration = SDL_GetTicks64() - last_tick; + if (frame_duration < delayNeeded) { +#ifdef CPU_THREADED + pthread_mutex_unlock(&cpu_mutex); +#endif + msleep(delayNeeded - frame_duration); + return; + } + last_tick = SDL_GetTicks64(); + } + +#ifdef CPU_THREADED + pthread_mutex_unlock(&cpu_mutex); +#endif +} + +// Blocking loop for running as a thread +void *cpu_loop(void *arg) { + while (running) { + cpu_step(); } return NULL; } @@ -415,8 +441,6 @@ SDL_Keycode ConvertKPToNonKP(SDL_Keycode keycode) { } } -uint8_t cpuSpeedTemp = 0; - int processEvent(SDL_Event e) { if (e.type == SDL_QUIT) { return 0; } else if (e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_RESIZED) { @@ -642,10 +666,18 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[]) SDL_Event e; Uint64 start; Uint64 end; +#ifdef CPU_THREADED pthread_create(&cpu_thread, NULL, cpu_loop, NULL); +#endif while (running) { start = SDL_GetTicks64(); +#ifndef CPU_THREADED + cpu_step(); +#endif +#ifdef CPU_THREADED + pthread_mutex_lock(&cpu_mutex); +#endif while (SDL_PollEvent(&e)) { running = processEvent(e); } @@ -671,7 +703,9 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[]) updateState(false); } } +#ifdef CPU_THREADED pthread_mutex_unlock(&cpu_mutex); +#endif end = SDL_GetTicks64(); const unsigned long timeNeeded = end - start; if (timeNeeded < delayNeeded) { @@ -706,8 +740,9 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[]) destroy_seven_segment(&displayF); destroy_seven_segment(&displayG); destroy_seven_segment(&displayH); - +#ifdef CPU_THREADED pthread_join(cpu_thread, NULL); +#endif if (renderer) SDL_DestroyRenderer(renderer); if (window) SDL_DestroyWindow(window); diff --git a/peripherals/switches.c b/peripherals/switches.c index 22261fd..6ccf3b0 100644 --- a/peripherals/switches.c +++ b/peripherals/switches.c @@ -85,7 +85,7 @@ void init_switches(Switches *switches, SDL_Renderer *renderer, int x, int y, int fprintf(stderr, "Failed to create texture: %s\n", SDL_GetError()); exit(EXIT_FAILURE); } - switches->value = (1 << 0) | (1 << 1); + switches->value = 0; generate_switch_rects(switches); update_switches_texture(renderer, switches); }