94 lines
2.1 KiB
C
94 lines
2.1 KiB
C
|
#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;
|
||
|
}
|