summaryrefslogtreecommitdiff
path: root/msim/sim.c
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-09-30 18:52:25 -0400
committerFreya Murphy <freya@freyacat.org>2024-09-30 18:52:25 -0400
commit4af200b00188e02b2c6207dfe494a3dd12556c5f (patch)
tree25d993117e6306907d1d3821ef4fca729390d221 /msim/sim.c
parentupdate runtime to return exit code from main (diff)
downloadmips-4af200b00188e02b2c6207dfe494a3dd12556c5f.tar.gz
mips-4af200b00188e02b2c6207dfe494a3dd12556c5f.tar.bz2
mips-4af200b00188e02b2c6207dfe494a3dd12556c5f.zip
msim done (ish)
Diffstat (limited to 'msim/sim.c')
-rw-r--r--msim/sim.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/msim/sim.c b/msim/sim.c
new file mode 100644
index 0000000..9e0d518
--- /dev/null
+++ b/msim/sim.c
@@ -0,0 +1,93 @@
+#include <merror.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "sim.h"
+#include "melf.h"
+
+void sim_dump_reg(struct simulator *sim)
+{
+ const char *names[32] = {
+ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1",
+ "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3",
+ "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp",
+ "fp", "ra"
+ };
+
+ for (uint32_t i = 0; i < 8; i++) {
+ for (uint32_t j = 0; j < 4; j++) {
+ if (j != 0)
+ fputc(' ', stderr);
+ int idx = i+j*8;
+ fprintf(stderr, "$%s:\t0x%08x", names[idx], sim->reg[idx]);
+ }
+ fputc('\n', stderr);
+ }
+}
+
+__attribute__((format(printf, 2, 3)))
+_Noreturn void sim_dump(struct simulator *sim, const char *format, ...) {
+
+ va_list list;
+ va_start(list, format);
+
+ // header
+ fprintf(stderr, "\n\t\t!!! An exception has occurred !!!\n\n");
+ fprintf(stderr, "\033[31merror: \033[0m");
+ vfprintf(stderr, format, list);
+ fputc('\n', stderr);
+
+ // pc
+ uint32_t pc = sim->current_pc;
+ fprintf(stderr, "pc: 0x%08x\n", pc);
+
+ if (pc >= sim->text_min && pc < sim->text_max)
+ fprintf(stderr, "ins: 0x%08x\n", B32(* (uint32_t *) (uintptr_t) pc));
+
+ // registers
+ fprintf(stderr, "registers:\n");
+ sim_dump_reg(sim);
+
+ exit(1);
+}
+
+void sim_step(struct simulator *sim)
+{
+ if (sim->pc < sim->text_min || sim->pc >= sim->text_max)
+ sim_dump(sim, "program counter reached non executable memory");
+
+ uint32_t ins = * (uint32_t *) (uintptr_t) sim->pc;
+ sim->pc += 4;
+ sim_ins(sim, ins);
+ sim->current_pc = sim->pc;
+}
+
+_Noreturn void sim_run(struct simulator *sim)
+{
+ sim->pc = sim->entry;
+ sim->current_pc = sim->pc;
+ while (1)
+ sim_step(sim);
+}
+
+int sim_init(struct simulator *sim, struct simulator_args *args) {
+ memset(sim->reg, 0, sizeof(uint32_t) * 32);
+ sim->data_max = MEM_DATA_ADDR;
+ sim->data_min = MEM_DATA_ADDR;
+ sim->text_max = MEM_TEXT_ADDR;
+ sim->text_min = MEM_TEXT_ADDR;
+ sim->args = args;
+
+ // load executable
+ if (sim_load_file(sim))
+ return M_ERROR;
+
+ // check entry
+ if (sim->entry < sim->text_min || sim->entry >= sim->text_max) {
+ ERROR("elf entrypoint invalid");
+ return M_ERROR;
+ }
+
+ return M_SUCCESS;
+}