Fancy disassembling in expdump.
This commit is contained in:
parent
ac03695764
commit
9a69d7d3d7
1 changed files with 96 additions and 10 deletions
106
libvm/expdump.c
106
libvm/expdump.c
|
@ -22,6 +22,55 @@
|
||||||
|
|
||||||
#define DEBUG_VAL(x) fprintf(stderr, #x " = %d\n", x)
|
#define DEBUG_VAL(x) fprintf(stderr, #x " = %d\n", x)
|
||||||
|
|
||||||
|
struct PredefinedCmd
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
Instruction instr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PredefinedCmd namedCommands[] =
|
||||||
|
{
|
||||||
|
{ "nop",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||||
|
{ "push",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "drop",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||||
|
{ "dup",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_PEEK, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "jmp",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_JUMP } },
|
||||||
|
{ "jmpi",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_JUMP } },
|
||||||
|
{ "ret",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_JUMP } },
|
||||||
|
{ "load",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_LOAD, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "loadi",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_LOAD, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "store",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_POP, VM_CMD_STORE, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||||
|
{ "storei",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_STORE, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||||
|
{ "get",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_GET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "geti",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_GET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "set",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_POP, VM_CMD_SET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||||
|
{ "seti",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_SET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||||
|
{ "bpget",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_BPGET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "bpset",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_BPSET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||||
|
{ "spget",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_SPGET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "spset",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_SPSET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||||
|
{ "cpget",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_CPGET, 1, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "add",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "sub",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 1, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "cmp",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 1, VM_FLAG_YES, VM_OUTPUT_DISCARD } },
|
||||||
|
{ "mul",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 2, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "div",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 3, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "mod",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 4, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "and",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 5, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "or",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 6, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "xor",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 7, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "not",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_MATH, 8, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "rol",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 9, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "ror",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 10, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "asl",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 11, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "asr",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 12, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "shl",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 13, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "shr",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 14, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||||
|
{ "syscall",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_SYSCALL, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||||
|
{ "hwio",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_HWIO, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
const char *commandStrings[] =
|
const char *commandStrings[] =
|
||||||
{
|
{
|
||||||
// VM_CMD_COPY 0
|
// VM_CMD_COPY 0
|
||||||
|
@ -52,33 +101,58 @@ const char *commandStrings[] =
|
||||||
"hwio",
|
"hwio",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int disassembleVerbose = 0;
|
||||||
|
|
||||||
void disassemble(Instruction *list, uint32_t count, FILE *f)
|
void disassemble(Instruction *list, uint32_t count, FILE *f)
|
||||||
{
|
{
|
||||||
|
int v = disassembleVerbose;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
Instruction instr = list[i];
|
Instruction instr = list[i];
|
||||||
|
|
||||||
fprintf(f, "\t");
|
fprintf(f, "%8X: ", i);
|
||||||
|
|
||||||
fprintf(f, "%6x ", i);
|
struct PredefinedCmd *knownInstruction = NULL;
|
||||||
|
|
||||||
|
for (int j = 0; j < sizeof(namedCommands) / sizeof(struct PredefinedCmd); j++)
|
||||||
|
{
|
||||||
|
if (memcmp(&instr, &namedCommands[j].instr, sizeof(Instruction) - sizeof(uint32_t)) == 0) {
|
||||||
|
knownInstruction = &namedCommands[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (knownInstruction != NULL)
|
||||||
|
{
|
||||||
|
fprintf(f, "%s", knownInstruction->name);
|
||||||
|
if (instr.input0 == VM_INPUT_ARG)
|
||||||
|
{
|
||||||
|
if(instr.output == VM_OUTPUT_JUMP || instr.output == VM_OUTPUT_JUMPR)
|
||||||
|
fprintf(f, " 0x%X", instr.argument);
|
||||||
|
else
|
||||||
|
fprintf(f, " %d", instr.argument);
|
||||||
|
}
|
||||||
|
fprintf(f, "\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (instr.execN)
|
switch (instr.execN)
|
||||||
{
|
{
|
||||||
case VM_EXEC_0: fprintf(f, "[ex(n)=0] "); break;
|
case VM_EXEC_0: fprintf(f, "[ex(n)=0] "); break;
|
||||||
case VM_EXEC_1: fprintf(f, "[ex(n)=1] "); break;
|
case VM_EXEC_1: fprintf(f, "[ex(n)=1] "); break;
|
||||||
case VM_EXEC_X: fprintf(f, "[ex(n)=x] "); break;
|
case VM_EXEC_X: if (v) fprintf(f, "[ex(n)=x] "); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (instr.execZ)
|
switch (instr.execZ)
|
||||||
{
|
{
|
||||||
case VM_EXEC_0: fprintf(f, "[ex(z)=0] "); break;
|
case VM_EXEC_0: fprintf(f, "[ex(z)=0] "); break;
|
||||||
case VM_EXEC_1: fprintf(f, "[ex(z)=1] "); break;
|
case VM_EXEC_1: fprintf(f, "[ex(z)=1] "); break;
|
||||||
case VM_EXEC_X: fprintf(f, "[ex(z)=x] "); break;
|
case VM_EXEC_X: if (v) fprintf(f, "[ex(z)=x] "); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (instr.input0)
|
switch (instr.input0)
|
||||||
{
|
{
|
||||||
case VM_INPUT_ZERO: fprintf(f, "[i0:zero] "); break;
|
case VM_INPUT_ZERO: if (v) fprintf(f, "[i0:zero] "); break;
|
||||||
case VM_INPUT_POP: fprintf(f, "[i0:pop] "); break;
|
case VM_INPUT_POP: fprintf(f, "[i0:pop] "); break;
|
||||||
case VM_INPUT_PEEK: fprintf(f, "[i0:peek] "); break;
|
case VM_INPUT_PEEK: fprintf(f, "[i0:peek] "); break;
|
||||||
case VM_INPUT_ARG: fprintf(f, "[i0:arg] "); break;
|
case VM_INPUT_ARG: fprintf(f, "[i0:arg] "); break;
|
||||||
|
@ -86,7 +160,7 @@ void disassemble(Instruction *list, uint32_t count, FILE *f)
|
||||||
|
|
||||||
switch (instr.input1)
|
switch (instr.input1)
|
||||||
{
|
{
|
||||||
case VM_INPUT_ZERO: fprintf(f, "[i1:zero] "); break;
|
case VM_INPUT_ZERO: if (v) fprintf(f, "[i1:zero] "); break;
|
||||||
case VM_INPUT_POP: fprintf(f, "[i1:pop] "); break;
|
case VM_INPUT_POP: fprintf(f, "[i1:pop] "); break;
|
||||||
case VM_INPUT_PEEK: fprintf(f, "[i1:peek] "); break;
|
case VM_INPUT_PEEK: fprintf(f, "[i1:peek] "); break;
|
||||||
case VM_INPUT_ARG: fprintf(f, "[i1:arg] "); break;
|
case VM_INPUT_ARG: fprintf(f, "[i1:arg] "); break;
|
||||||
|
@ -97,17 +171,28 @@ void disassemble(Instruction *list, uint32_t count, FILE *f)
|
||||||
else
|
else
|
||||||
fprintf(f, "undefined [cmd:%d]", instr.command);
|
fprintf(f, "undefined [cmd:%d]", instr.command);
|
||||||
|
|
||||||
fprintf(f, " [ci:%d]", instr.cmdinfo);
|
if (instr.cmdinfo != 0)
|
||||||
|
{
|
||||||
|
fprintf(f, " [ci:%d]", instr.cmdinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instr.argument != 0 || instr.input0 == VM_INPUT_ARG)
|
||||||
|
{
|
||||||
|
if (instr.output == VM_OUTPUT_JUMP || instr.output == VM_OUTPUT_JUMPR)
|
||||||
|
fprintf(f, " 0x%X", instr.argument);
|
||||||
|
else
|
||||||
|
fprintf(f, " %d", instr.argument);
|
||||||
|
}
|
||||||
|
|
||||||
switch (instr.flags)
|
switch (instr.flags)
|
||||||
{
|
{
|
||||||
case VM_FLAG_NO: fprintf(f, " [f:no]"); break;
|
case VM_FLAG_NO: if (v) fprintf(f, " [f:no]"); break;
|
||||||
case VM_FLAG_YES: fprintf(f, " [f:yes]"); break;
|
case VM_FLAG_YES: fprintf(f, " [f:yes]"); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (instr.output)
|
switch (instr.output)
|
||||||
{
|
{
|
||||||
case VM_OUTPUT_DISCARD: fprintf(f, " [r:discard]"); break;
|
case VM_OUTPUT_DISCARD: if (v) fprintf(f, " [r:discard]"); break;
|
||||||
case VM_OUTPUT_JUMP: fprintf(f, " [r:jump]"); break;
|
case VM_OUTPUT_JUMP: fprintf(f, " [r:jump]"); break;
|
||||||
case VM_OUTPUT_JUMPR: fprintf(f, " [r:jumpr]"); break;
|
case VM_OUTPUT_JUMPR: fprintf(f, " [r:jumpr]"); break;
|
||||||
case VM_OUTPUT_PUSH: fprintf(f, " [r:push]"); break;
|
case VM_OUTPUT_PUSH: fprintf(f, " [r:push]"); break;
|
||||||
|
@ -128,12 +213,13 @@ int main(int argc, char **argv)
|
||||||
int disassembleSections = 0;
|
int disassembleSections = 0;
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
while ((c = getopt(argc, argv, "smd")) != -1)
|
while ((c = getopt(argc, argv, "smdD")) != -1)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 's': dumpSections = 1; break;
|
case 's': dumpSections = 1; break;
|
||||||
case 'm': dumpMetas = 1; break;
|
case 'm': dumpMetas = 1; break;
|
||||||
|
case 'D': disassembleVerbose = 1;
|
||||||
case 'd': disassembleSections = 1; break;
|
case 'd': disassembleSections = 1; break;
|
||||||
case '?':
|
case '?':
|
||||||
if (optopt == 'o' || optopt == 'c' || optopt == 'd')
|
if (optopt == 'o' || optopt == 'c' || optopt == 'd')
|
||||||
|
|
Loading…
Reference in a new issue