diff options
author | Freya Murphy <freya@freyacat.org> | 2024-09-30 18:52:25 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2024-09-30 18:52:25 -0400 |
commit | 4af200b00188e02b2c6207dfe494a3dd12556c5f (patch) | |
tree | 25d993117e6306907d1d3821ef4fca729390d221 /msim/sim.c | |
parent | update runtime to return exit code from main (diff) | |
download | mips-4af200b00188e02b2c6207dfe494a3dd12556c5f.tar.gz mips-4af200b00188e02b2c6207dfe494a3dd12556c5f.tar.bz2 mips-4af200b00188e02b2c6207dfe494a3dd12556c5f.zip |
msim done (ish)
Diffstat (limited to 'msim/sim.c')
-rw-r--r-- | msim/sim.c | 93 |
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; +} |