/* NED1 Simulator */
/* -------------------------------------------------------------------------- */
-// TODO: Make a bunch of functions private in this file.
#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"
-uint32_t
+static uint32_t
generate_binary_psw(struct NEDstate * state)
{
uint32_t psw = 0;
return psw;
}
-void
+static void
ram_w_byte(struct NEDstate * state, uint32_t address, uint8_t data)
{
state->ram[address-RAM_BASE_ADDRESS] = data;
}
-uint8_t
+static uint8_t
ram_r_byte(struct NEDstate * state, uint32_t address)
{
return state->ram[address-RAM_BASE_ADDRESS];
/* For now, with only a terminal for IO, we pick off IO requests when accessing RAM. */
-void
+static void
ram_w_word(struct NEDstate * state, uint32_t address, uint32_t data)
{
if (address >= RAM_BASE_ADDRESS) {
return 0b0;
}
-uint32_t
+static uint32_t
fetch_instruction_word(struct NEDstate * state)
{
uint32_t word = ram_r_word(state, state->active_thread->pc);
return word;
}
-void
+static void
stack_w(struct NEDthread * thread, uint32_t value, uint8_t offset)
{
thread->stack[thread->sp - (offset + 1)] = value;
}
-uint32_t
+static uint32_t
stack_r(struct NEDthread * thread, uint8_t offset)
{
return thread->stack[thread->sp - (offset + 1)];
}
-void
+static void
stack_push(struct NEDthread * thread, uint32_t value)
{
thread->stack[thread->sp++] = value;
}
-uint32_t
+static uint32_t
stack_pop(struct NEDthread * thread)
{
return thread->stack[--thread->sp];
}
-void
+static void
set_psw_flags(uint32_t word, struct NEDstate * state)
{
if (word == 0) {
}
}
-void
+static void
ned_instruction_and(struct NEDstate * state)
{
uint32_t operand1 = stack_pop(state->active_thread);
set_psw_flags(stack_r(state->active_thread,0), state);
}
-void
+static void
ned_instruction_or(struct NEDstate * state)
{
uint32_t operand1 = stack_pop(state->active_thread);
set_psw_flags(stack_r(state->active_thread,0), state);
}
-void
+static void
ned_instruction_not(struct NEDstate * state)
{
stack_push(state->active_thread, ~stack_pop(state->active_thread));
set_psw_flags(stack_r(state->active_thread,0), state);
}
-void
+static void
ned_instruction_xor(struct NEDstate * state)
{
uint32_t operand1 = stack_pop(state->active_thread);
set_psw_flags(stack_r(state->active_thread,0), state);
}
-void
+static void
ned_instruction_add(struct NEDstate * state)
{
uint32_t operand1 = stack_pop(state->active_thread);
set_psw_flags(stack_r(state->active_thread,0), state);
}
-void
+static void
ned_instruction_shift(struct NEDstate * state)
{
- /* TODO: Bounds check: Either all inputs are valid OR shift_by < 32. */
- /* I guess this also depends if I'm shifting-and-dropping, or barrel-shifting. */
- /* How should I pad for a right shift if I shift-and-drop? Sign extend? */
uint32_t shift_by = stack_pop(state->active_thread);
uint32_t word = stack_pop(state->active_thread);
if (shift_by & 0x80000000) {
set_psw_flags(stack_r(state->active_thread,0), state);
}
-void
+static void
ned_instruction_test(struct NEDstate * state)
{
uint32_t word = stack_pop(state->active_thread);
set_psw_flags(word, state);
}
-void
+static void
ned_instruction_jmp(struct NEDstate * state)
{
state->active_thread->pc = stack_pop(state->active_thread);
// The SC is caught and reset by the main loop since the PC changed.
}
-void
+static void
ned_instruction_swap(struct NEDstate * state)
{
uint32_t temp1 = stack_pop(state->active_thread);
set_psw_flags(stack_r(state->active_thread,0), state);
}
-void
+static void
ned_instruction_brz(struct NEDstate * state)
{
uint32_t new_pc = stack_pop(state->active_thread);
}
}
-void
+static void
ned_instruction_load(struct NEDstate * state)
{
uint32_t address = stack_pop(state->active_thread);
set_psw_flags(stack_r(state->active_thread,0), state);
}
-void
+static void
ned_instruction_store(struct NEDstate * state)
{
uint32_t address = stack_pop(state->active_thread);
ram_w_word(state, address, data);
}
-void
+static void
ned_instruction_halt(struct NEDstate * state)
{
printf("Halting.\n");
state->halted = true;
}
-void
+static void
execute_syllable(struct NEDstate * state, enum syllables syllable)
{
if (syllable & 0b100000) { /* Check the first bit of the syllable. 1 means IM_x. */
}
}
-uint8_t
+static uint8_t
extract_syllable_from_word(uint32_t word, uint8_t index)
{
uint32_t mask = 0b111111 << 6*(4-index);
return (word & mask) >> 6*(4-index);
}
-void
+static void
parse_aout_file(FILE * input, struct exec * aout_exec, uint8_t * text_segment,
struct nlist ** symbol_table, uint32_t * symbol_count)
{
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++; // TODO: Should this be part of extract_syllable_from_word()? After all, incrementing the PC is done in fetch_instruction_word().
- uint32_t pre_execution_pc = state->active_thread->pc; // TODO: This is so we can catch JMP/JSR/etc subroutines that need the SC to be reset to zero.
+ 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.
+ /* 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) {
- // Just executed the last syllable in this word, time to follow the PC to the next word.
+ /* 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.
+ /* More syllables remain to be executed in this instruction word. */
state->hack->resume_word = true;
state->hack->iw = iw;
}