#include <stdio.h>
#include <stdint.h>
-#include <inttypes.h>
#include <stdlib.h>
#include <stdbool.h>
-#include <unistd.h>
-#include <fcntl.h>
#include <string.h>
#include <errno.h>
-#include <time.h>
-#include <termios.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
#include "a.out.h"
#include "simulator.h"
}
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));
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)\n",
+ *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;
}
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. */
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. */