Improves disassembler: Now selects the best match from all mnemonics and only displays the required modificators.

This commit is contained in:
Felix Queißner 2016-07-01 09:40:14 +02:00
parent 1fec9927c1
commit a24fb63449

View file

@ -39,6 +39,11 @@ static const char *commandStrings[] =
"hwio",
};
uint32_t instructionValue(const instruction_t *i)
{
return *((const uint32_t*)i);
}
void disassemble(instruction_t *list, uint32_t count, uint32_t base, FILE *f)
{
bool v = disasmOptions.verbose;
@ -49,69 +54,83 @@ void disassemble(instruction_t *list, uint32_t count, uint32_t base, FILE *f)
fprintf(f, "%8X: ", base + i);
const mnemonic_t *knownInstruction = NULL;
uint32_t thisValue = instructionValue(&instr);
int maxDistance = 1024; // should be enough to cover all differences :P
for (int j = 0; mnemonics[j].name != NULL; j++)
{
if (memcmp(&instr, &mnemonics[j].instr, sizeof(instruction_t) - sizeof(uint32_t)) == 0) {
if(mnemonics[j].instr.command != instr.command)
continue;
int thatValue = instructionValue(&mnemonics[j].instr);
int dist = __builtin_popcount(thisValue ^ thatValue);
// if (memcmp(&instr, &mnemonics[j].instr, sizeof(instruction_t) - sizeof(uint32_t)) == 0) {
if(dist < maxDistance) {
maxDistance = dist;
knownInstruction = &mnemonics[j];
break;
}
}
if(knownInstruction == NULL) {
fprintf(stderr, "Could not find matching instruction in mnemonics. This is weird.\n");
abort();
}
if (knownInstruction != NULL)
instruction_t ref = knownInstruction->instr;
if(instr.execN != ref.execN)
{
fprintf(f, "%s", knownInstruction->name);
if (instr.argument != 0 || instr.input0 == VM_INPUT_ARG)
switch (instr.execN)
{
if(instr.output == VM_OUTPUT_JUMP || instr.output == VM_OUTPUT_JUMPR)
fprintf(f, " 0x%X", instr.argument);
else
fprintf(f, " %d", instr.argument);
case VM_EXEC_0: fprintf(f, "[ex(n)=0] "); break;
case VM_EXEC_1: fprintf(f, "[ex(n)=1] "); break;
case VM_EXEC_X: if (v) fprintf(f, "[ex(n)=x] "); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
}
fprintf(f, "\n");
continue;
}
switch (instr.execN)
if(instr.execZ != ref.execZ)
{
case VM_EXEC_0: fprintf(f, "[ex(n)=0] "); break;
case VM_EXEC_1: fprintf(f, "[ex(n)=1] "); break;
case VM_EXEC_X: if (v) fprintf(f, "[ex(n)=x] "); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
switch (instr.execZ)
{
case VM_EXEC_0: fprintf(f, "[ex(z)=0] "); break;
case VM_EXEC_1: fprintf(f, "[ex(z)=1] "); break;
case VM_EXEC_X: if (v) fprintf(f, "[ex(z)=x] "); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
}
}
switch (instr.execZ)
if(instr.input0 != ref.input0)
{
case VM_EXEC_0: fprintf(f, "[ex(z)=0] "); break;
case VM_EXEC_1: fprintf(f, "[ex(z)=1] "); break;
case VM_EXEC_X: if (v) fprintf(f, "[ex(z)=x] "); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
switch (instr.input0)
{
case VM_INPUT_ZERO: if (v) fprintf(f, "[i0:zero] "); break;
case VM_INPUT_POP: fprintf(f, "[i0:pop] "); break;
case VM_INPUT_PEEK: fprintf(f, "[i0:peek] "); break;
case VM_INPUT_ARG: fprintf(f, "[i0:arg] "); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
}
}
switch (instr.input0)
if(instr.input1 != ref.input1)
{
case VM_INPUT_ZERO: if (v) fprintf(f, "[i0:zero] "); break;
case VM_INPUT_POP: fprintf(f, "[i0:pop] "); break;
case VM_INPUT_PEEK: fprintf(f, "[i0:peek] "); break;
case VM_INPUT_ARG: fprintf(f, "[i0:arg] "); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
switch (instr.input1)
{
case VM_INPUT_ZERO: if (v) fprintf(f, "[i1:zero] "); break;
case VM_INPUT_POP: fprintf(f, "[i1:pop] "); break;
// case VM_INPUT_PEEK: fprintf(f, "[i1:peek] "); break;
// case VM_INPUT_ARG: fprintf(f, "[i1:arg] "); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
}
}
fprintf(f, "%s", knownInstruction->name);
// if (instr.command <= 12)
// fprintf(f, "%s", commandStrings[instr.command]);
// else
// fprintf(f, "undefined [cmd:%d]", instr.command);
switch (instr.input1)
{
case VM_INPUT_ZERO: if (v) fprintf(f, "[i1:zero] "); break;
case VM_INPUT_POP: fprintf(f, "[i1:pop] "); break;
// case VM_INPUT_PEEK: fprintf(f, "[i1:peek] "); break;
// case VM_INPUT_ARG: fprintf(f, "[i1:arg] "); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
}
if (instr.command <= 12)
fprintf(f, "%s", commandStrings[instr.command]);
else
fprintf(f, "undefined [cmd:%d]", instr.command);
if (instr.cmdinfo != 0)
if (instr.cmdinfo != ref.cmdinfo)
{
fprintf(f, " [ci:%d]", instr.cmdinfo);
}
@ -123,21 +142,25 @@ void disassemble(instruction_t *list, uint32_t count, uint32_t base, FILE *f)
else
fprintf(f, " %d", instr.argument);
}
switch (instr.flags)
if(instr.flags != ref.flags)
{
case VM_FLAG_NO: if (v) fprintf(f, " [f:no]"); break;
case VM_FLAG_YES: fprintf(f, " [f:yes]"); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
switch (instr.flags)
{
case VM_FLAG_NO: if (v) fprintf(f, " [f:no]"); break;
case VM_FLAG_YES: fprintf(f, " [f:yes]"); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
}
}
switch (instr.output)
if(instr.output != ref.output)
{
case VM_OUTPUT_DISCARD: fprintf(f, " [r:discard]"); break;
case VM_OUTPUT_JUMP: fprintf(f, " [r:jump]"); break;
case VM_OUTPUT_JUMPR: fprintf(f, " [r:jumpr]"); break;
case VM_OUTPUT_PUSH: fprintf(f, " [r:push]"); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
switch (instr.output)
{
case VM_OUTPUT_DISCARD: fprintf(f, " [r:discard]"); break;
case VM_OUTPUT_JUMP: fprintf(f, " [r:jump]"); break;
case VM_OUTPUT_JUMPR: fprintf(f, " [r:jumpr]"); break;
case VM_OUTPUT_PUSH: fprintf(f, " [r:push]"); break;
default: fprintf(stderr, "Invalid code @%d\n", base + i); abort();
}
}
fprintf(f, "\n");