X-Git-Url: http://git.subgeniuskitty.com/screensavers/.git/blobdiff_plain/0e83e980b0dc355b642c069db82bb4aebfdf8228..b73247cfaa571f5f162eca6e55ee7ea803d31dd7:/hacks/NEDsim/simulator.c diff --git a/hacks/NEDsim/simulator.c b/hacks/NEDsim/simulator.c index 73623dc..ec1db20 100644 --- a/hacks/NEDsim/simulator.c +++ b/hacks/NEDsim/simulator.c @@ -7,21 +7,10 @@ #include #include -#include #include #include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include "a.out.h" #include "simulator.h" @@ -375,7 +364,7 @@ parse_aout_file(FILE * input, struct exec * aout_exec, uint8_t * text_segment, } struct NEDstate * -init_simulator(char * input_file) +init_simulator(char * input_file, const uint8_t * blob, const size_t * blob_size) { struct NEDstate * state = malloc(sizeof(struct NEDstate)); state->hack = malloc(sizeof(struct NEDhack)); @@ -392,20 +381,39 @@ init_simulator(char * input_file) state->hack->resume_word = false; /* Load an initial image into memory. */ - struct exec aout_exec; - struct nlist * symbol_table; - uint32_t symbol_count; - FILE * input = NULL; - if ((input = fopen(input_file, "r")) == NULL) { - fprintf(stderr, "ERROR: %s: %s\n", input_file, strerror(errno)); + if (input_file) { + struct exec aout_exec; + struct nlist * symbol_table; + uint32_t symbol_count; + FILE * input = NULL; + if ((input = fopen(input_file, "r")) == NULL) { + fprintf(stderr, "ERROR: %s: %s\n", input_file, strerror(errno)); + state->halted = true; + } + parse_aout_file(input, &aout_exec, state->ram, &symbol_table, &symbol_count); + fclose(input); + for (size_t i=0; i < symbol_count; i++) { + free(symbol_table[i].n_un.n_name); + } + free(symbol_table); + } else if (blob && blob_size) { + if (*blob_size <= RAM_LENGTH) { + size_t index = *blob_size; + while (index) { + index--; + state->ram[index] = blob[index]; + } + } else { + fprintf(stderr, + "ERROR: Built-in NED1 program is larger than simulated RAM (%zu vs %d bytes)", + *blob_size, RAM_LENGTH + ); + state->halted = true; + } + } else { + fprintf(stderr, "ERROR: No suitable binary image passed when initializing simulator.\n"); state->halted = true; } - parse_aout_file(input, &aout_exec, state->ram, &symbol_table, &symbol_count); - fclose(input); - for (size_t i=0; i < symbol_count; i++) { - free(symbol_table[i].n_un.n_name); - } - free(symbol_table); return state; } @@ -419,8 +427,10 @@ run_simulator(struct NEDstate * state) uint32_t iw; if (state->hack->resume_word) { iw = state->hack->iw; + state->active_thread->sc++; } else { iw = fetch_instruction_word(state); + state->active_thread->sc = 0; } /* Decode instruction word format and execute. */ @@ -428,18 +438,15 @@ run_simulator(struct NEDstate * state) stack_push(state->active_thread, (iw << 1)); } else if ((iw & (0b11 << 30)) == 0) { /* Instruction word is type C. */ uint8_t syllable = extract_syllable_from_word(iw, state->active_thread->sc); - state->active_thread->sc++; /* The following variable allows us to catch JMP/BRZ instructions that */ /* jump to a new PC and need the SC reset. */ uint32_t pre_execution_pc = state->active_thread->pc; execute_syllable(state, syllable); if (state->active_thread->pc != pre_execution_pc) { /* Jumped to a new address, so prepare to execute a new instruction word. */ - state->active_thread->sc = 0; state->hack->resume_word = false; - } else if (state->active_thread->sc >= SPW) { + } else if (state->active_thread->sc >= SPW-1) { /* Just executed the last syllable in this word, follow the PC to the next word. */ - state->active_thread->sc = 0; state->hack->resume_word = false; } else { /* More syllables remain to be executed in this instruction word. */