Add non multithread mode
This commit is contained in:
@@ -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') {
|
||||
|
@@ -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.
|
||||
|
87
main.c
87
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);
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user