#include #include #include #include #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; }