mips/msim/sim.c

94 lines
2.1 KiB
C
Raw Permalink Normal View History

2024-09-30 22:52:25 +00:00
#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;
}