#define _GNU_SOURCE
+#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#define PROGSTART 0x20000000
#define MSR_64 (1UL<<63)
+#define MSR_FP (1UL<<13)
#define MSR_LE (1UL<<0)
enum {
}
}
+static void disassemble(const char binpath[], char *disasm, const unsigned len) {
+
+ char buf[PATH_MAX];
+ snprintf(buf, PATH_MAX,
+ "objdump -b binary -m powerpc --no-show-raw-insn -D %s",
+ binpath);
+ buf[PATH_MAX - 1] = '\0';
+
+ FILE *f = popen(buf, "r");
+ if (!f) {
+ printf("Disassembly failed, trace won't have disas\n");
+ return;
+ }
+
+ while (fgets(buf, PATH_MAX, f)) {
+ if (buf[0] != ' ')
+ continue;
+ const char *ptr = strchr(buf, ':');
+ if (!ptr)
+ continue;
+ nukenewline(buf);
+
+ const unsigned addr = strtol(buf, NULL, 16) / 4 * 32;
+ if (addr / 32 + 1 >= len)
+ abort();
+
+ ptr++;
+ while (isspace(*ptr))
+ ptr++;
+
+ strncpy(&disasm[addr], ptr, 32);
+ disasm[addr + 31] = '\0';
+ }
+
+ pclose(f);
+}
+
int main(int argc, char **argv) {
const struct option longopts[] = {
char dumps[MAXDUMPS][PATH_MAX];
unsigned num_dumps = 0;
uint8_t *ram, *progmem;
- const char *binpath;
+ const char *binpath = NULL;
+ const char *disasm = NULL;
// Yes, we're frugal
if (posix_memalign((void **) &ram, 64 * 1024, RAMSIZE))
regs.lr = -1;
regs.pc = PROGSTART;
- regs.msr = MSR_64 | MSR_LE;
+ regs.msr = MSR_64 | MSR_FP | MSR_LE;
while (1) {
const int c = getopt_long(argc, argv, opts, longopts, NULL);
abort();
fclose(binary);
+
+ if (trace) {
+ const unsigned disaslen = binlen / 4 + 64;
+ disasm = calloc(disaslen, 32);
+
+ disassemble(binpath, (char *) disasm, disaslen);
+ }
+
kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC);
if (kvm < 0) {
printf("Failed to open kvm, perhaps you lack permissions?\n");
abort();
// Runtime
+ uint64_t pc = PROGSTART;
+ unsigned i;
while (1) {
if (ioctl(vcpu, KVM_RUN, NULL) == -1)
abort();
- printf("Exited because %u\n", run->exit_reason);
+
+ if (ioctl(vcpu, KVM_GET_REGS, ®s) == -1)
+ abort();
+ //printf("PC %lx LR %lx\n", regs.pc, regs.lr);
+
+ if (run->exit_reason == KVM_EXIT_DEBUG) {
+ if (trace) {
+ getfpregs(vcpu, &fpregs);
+
+ fprintf(trace, "%lx: %s\n", pc, &disasm[(pc - PROGSTART) / 4 * 32]);
+ for (i = 0; i < 32; i++) {
+ if (i % 8 == 0)
+ fprintf(trace, "GPR: ");
+ fprintf(trace, "%08lx", regs.gpr[i]);
+ if (i % 8 == 7)
+ fprintf(trace, "\n");
+ else
+ fprintf(trace, " ");
+ }
+ for (i = 0; i < 32; i++) {
+ if (i % 8 == 0)
+ fprintf(trace, "FPR: ");
+ fprintf(trace, "%08lx", fpregs.fpr[i]);
+ if (i % 8 == 7)
+ fprintf(trace, "\n");
+ else
+ fprintf(trace, " ");
+ }
+ }
+ } else if (regs.pc < PROGSTART || regs.pc > PROGSTART + binlen) {
+ // Normal exit by blr
+ break;
+ } else {
+ printf("Unexpected exit because %u\n", run->exit_reason);
+ break;
+ }
+
+ pc = regs.pc;
}
- unsigned i;
for (i = 0; i < num_dumps; i++) {
dump(dumps[i], ram);
}
free(progmem);
free(ram);
free((char *) binpath);
+ free((char *) disasm);
return 0;
}