mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-01 08:31:45 +00:00
Improve disassembly of branch instructions
- I kept getting confused trying to read these instructions, so now their disassembly looks more MIPS-like: * All mnemonics have had 'b' prepended to them for "branch". * The CMP_CHECK bit alters the displayed mnemonic for the inverted versions. e.g. BEQ can be displayed as BNE. * The following JMP instruction that encodes the branch destination has been folded into the disassembly of the branch instruction. Unlike MIPS, I chose to display it offset from the branch check with => instead of another comma.
This commit is contained in:
parent
775e33ede7
commit
5d2cbf4ecb
3 changed files with 85 additions and 34 deletions
|
@ -193,6 +193,7 @@ enum EVMOpMode
|
|||
MODE_IMMS,
|
||||
MODE_IMMZ,
|
||||
MODE_JOINT,
|
||||
MODE_CMP,
|
||||
|
||||
MODE_PARAM,
|
||||
MODE_THROW,
|
||||
|
@ -209,6 +210,7 @@ enum EVMOpMode
|
|||
MODE_AUNUSED = MODE_UNUSED << MODE_ASHIFT,
|
||||
MODE_AIMMS = MODE_IMMS << MODE_ASHIFT,
|
||||
MODE_AIMMZ = MODE_IMMZ << MODE_ASHIFT,
|
||||
MODE_ACMP = MODE_CMP << MODE_ASHIFT,
|
||||
|
||||
MODE_BI = MODE_I << MODE_BSHIFT,
|
||||
MODE_BF = MODE_F << MODE_BSHIFT,
|
||||
|
|
|
@ -93,6 +93,17 @@
|
|||
#define I8RPRP MODE_AIMMZ | MODE_BP | MODE_CP
|
||||
#define I8RPKP MODE_AIMMZ | MODE_BP | MODE_CKP
|
||||
|
||||
#define CIRR MODE_ACMP | MODE_BI | MODE_CI
|
||||
#define CIRK MODE_ACMP | MODE_BI | MODE_CKI
|
||||
#define CIKR MODE_ACMP | MODE_BKI | MODE_CI
|
||||
#define CFRR MODE_ACMP | MODE_BF | MODE_CF
|
||||
#define CFRK MODE_ACMP | MODE_BF | MODE_CKF
|
||||
#define CFKR MODE_ACMP | MODE_BKF | MODE_CF
|
||||
#define CVRR MODE_ACMP | MODE_BV | MODE_CV
|
||||
#define CVRK MODE_ACMP | MODE_BV | MODE_CKV
|
||||
#define CPRR MODE_ACMP | MODE_BP | MODE_CP
|
||||
#define CPRK MODE_ACMP | MODE_BP | MODE_CKP
|
||||
|
||||
const VMOpInfo OpInfo[NUM_OPS] =
|
||||
{
|
||||
#define xx(op, name, mode) { #name, mode }
|
||||
|
@ -214,28 +225,51 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
int col;
|
||||
int mode;
|
||||
int a;
|
||||
bool cmp;
|
||||
char cmpname[8];
|
||||
|
||||
for (int i = 0; i < codesize; ++i)
|
||||
{
|
||||
name = OpInfo[code[i].op].Name;
|
||||
mode = OpInfo[code[i].op].Mode;
|
||||
a = code[i].a;
|
||||
cmp = (mode & MODE_ATYPE) == MODE_ACMP;
|
||||
|
||||
// String comparison encodes everything in a single instruction.
|
||||
if (code[i].op == OP_CMPS)
|
||||
{
|
||||
switch (a & CMP_METHOD_MASK)
|
||||
{
|
||||
case CMP_EQ: name = "eq"; break;
|
||||
case CMP_LT: name = "lt"; break;
|
||||
case CMP_LE: name = "le"; break;
|
||||
case CMP_EQ: name = "beq"; break;
|
||||
case CMP_LT: name = "blt"; break;
|
||||
case CMP_LE: name = "ble"; break;
|
||||
}
|
||||
mode = MODE_AIMMZ;
|
||||
mode |= (a & CMP_BK) ? MODE_BKS : MODE_BS;
|
||||
mode |= (a & CMP_CK) ? MODE_CKS : MODE_CS;
|
||||
a &= CMP_CHECK | CMP_APPROX;
|
||||
cmp = true;
|
||||
}
|
||||
if (cmp)
|
||||
{ // Comparison instruction. Modify name for inverted test.
|
||||
if (!(a & CMP_CHECK))
|
||||
{
|
||||
strcpy(cmpname, name);
|
||||
if (name[1] == 'e')
|
||||
{ // eq -> ne
|
||||
cmpname[1] = 'n', cmpname[2] = 'e';
|
||||
}
|
||||
else if (name[2] == 't')
|
||||
{ // lt -> ge
|
||||
cmpname[1] = 'g', cmpname[2] = 'e';
|
||||
}
|
||||
else
|
||||
{ // le -> gt
|
||||
cmpname[1] = 'g', cmpname[2] = 't';
|
||||
}
|
||||
name = cmpname;
|
||||
}
|
||||
}
|
||||
|
||||
printf_wrapper(out, "%08x: %02x%02x%02x%02x %-8s", i << 2, code[i].op, code[i].a, code[i].b, code[i].c, name);
|
||||
col = 0;
|
||||
switch (code[i].op)
|
||||
|
@ -299,7 +333,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
col = printf_wrapper(out, "f%d,f%d,%d", code[i].a, code[i].b, code[i].c);
|
||||
if (code[i].c < countof(FlopNames))
|
||||
{
|
||||
col +=printf_wrapper(out, " [%s]", FlopNames[code[i].c]);
|
||||
col += printf_wrapper(out, " [%s]", FlopNames[code[i].c]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -371,19 +405,34 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (cmp && i + 1 < codesize)
|
||||
{
|
||||
if (code[i+1].op != OP_JMP)
|
||||
{ // comparison instructions must be followed by jump
|
||||
col += printf_wrapper(out, " => *!*!*!*\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
col += printf_wrapper(out, " => %08x", (i + 2 + code[i+1].i24) << 2);
|
||||
}
|
||||
}
|
||||
if (col > 30)
|
||||
{
|
||||
col = 30;
|
||||
}
|
||||
printf_wrapper(out, "%*c", 30 - col, ';');
|
||||
if (code[i].op == OP_JMP || code[i].op == OP_TRY || code[i].op == OP_PARAMI)
|
||||
if (!cmp && (code[i].op == OP_JMP || code[i].op == OP_TRY || code[i].op == OP_PARAMI))
|
||||
{
|
||||
printf_wrapper(out, "%d\n", code[i].i24);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf_wrapper(out, "%d,%d,%d", code[i].a, code[i].b, code[i].c);
|
||||
if (code[i].op == OP_CALL_K || code[i].op == OP_TAIL_K)
|
||||
if (cmp && i + 1 < codesize && code[i+1].op == OP_JMP)
|
||||
{
|
||||
printf_wrapper(out, ",%d\n", code[++i].i24);
|
||||
}
|
||||
else if (code[i].op == OP_CALL_K || code[i].op == OP_TAIL_K)
|
||||
{
|
||||
printf_wrapper(out, " [%p]\n", callfunc);
|
||||
}
|
||||
|
@ -397,7 +446,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
|
||||
static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const VMScriptFunction *func)
|
||||
{
|
||||
if (mode == MODE_UNUSED)
|
||||
if (mode == MODE_UNUSED || mode == MODE_CMP)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -146,20 +146,20 @@ xx(ZAP_R, zap, RIRIRI), // dA = dB, with bytes zeroed where bits in C/dC are o
|
|||
xx(ZAP_I, zap, RIRII8),
|
||||
xx(ZAPNOT_R, zapnot, RIRIRI), // dA = dB, with bytes zeroed where bits in C/dC are zero
|
||||
xx(ZAPNOT_I, zapnot, RIRII8),
|
||||
xx(EQ_R, eq, I8RIRI), // if ((dB == dkC) != A) then pc++
|
||||
xx(EQ_K, eq, I8RIKI),
|
||||
xx(LT_RR, lt, I8RIRI), // if ((dkB < dkC) != A) then pc++
|
||||
xx(LT_RK, lt, I8RIKI),
|
||||
xx(LT_KR, lt, I8KIRI),
|
||||
xx(LE_RR, le, I8RIRI), // if ((dkB <= dkC) != A) then pc++
|
||||
xx(LE_RK, le, I8RIKI),
|
||||
xx(LE_KR, le, I8KIRI),
|
||||
xx(LTU_RR, ltu, I8RIRI), // if ((dkB < dkC) != A) then pc++ -- unsigned
|
||||
xx(LTU_RK, ltu, I8RIKI),
|
||||
xx(LTU_KR, ltu, I8KIRI),
|
||||
xx(LEU_RR, leu, I8RIRI), // if ((dkB <= dkC) != A) then pc++ -- unsigned
|
||||
xx(LEU_RK, leu, I8RIKI),
|
||||
xx(LEU_KR, leu, I8KIRI),
|
||||
xx(EQ_R, beq, CIRR), // if ((dB == dkC) != A) then pc++
|
||||
xx(EQ_K, beq, CIRK),
|
||||
xx(LT_RR, blt, CIRR), // if ((dkB < dkC) != A) then pc++
|
||||
xx(LT_RK, blt, CIRK),
|
||||
xx(LT_KR, blt, CIKR),
|
||||
xx(LE_RR, ble, CIRR), // if ((dkB <= dkC) != A) then pc++
|
||||
xx(LE_RK, ble, CIRK),
|
||||
xx(LE_KR, ble, CIKR),
|
||||
xx(LTU_RR, bltu, CIRR), // if ((dkB < dkC) != A) then pc++ -- unsigned
|
||||
xx(LTU_RK, bltu, CIRK),
|
||||
xx(LTU_KR, bltu, CIKR),
|
||||
xx(LEU_RR, bleu, CIRR), // if ((dkB <= dkC) != A) then pc++ -- unsigned
|
||||
xx(LEU_RK, bleu, CIRK),
|
||||
xx(LEU_KR, bleu, CIKR),
|
||||
|
||||
// Double-precision floating point math.
|
||||
xx(ADDF_RR, add, RFRFRF), // fA = fB + fkC
|
||||
|
@ -183,14 +183,14 @@ xx(MINF_RK, min, RFRFKF),
|
|||
xx(MAXF_RR, max, RFRFRF), // fA = max(fB),fkC)
|
||||
xx(MAXF_RK, max, RFRFKF),
|
||||
xx(FLOP, flop, RFRFI8), // fA = f(fB), where function is selected by C
|
||||
xx(EQF_R, eq, I8RFRF), // if ((fB == fkC) != (A & 1)) then pc++
|
||||
xx(EQF_K, eq, I8RFKF),
|
||||
xx(LTF_RR, lt, I8RFRF), // if ((fkB < fkC) != (A & 1)) then pc++
|
||||
xx(LTF_RK, lt, I8RFKF),
|
||||
xx(LTF_KR, lt, I8KFRF),
|
||||
xx(LEF_RR, le, I8RFRF), // if ((fkb <= fkC) != (A & 1)) then pc++
|
||||
xx(LEF_RK, le, I8RFKF),
|
||||
xx(LEF_KR, le, I8KFRF),
|
||||
xx(EQF_R, beq, CFRR), // if ((fB == fkC) != (A & 1)) then pc++
|
||||
xx(EQF_K, beq, CFRK),
|
||||
xx(LTF_RR, blt, CFRR), // if ((fkB < fkC) != (A & 1)) then pc++
|
||||
xx(LTF_RK, blt, CFRK),
|
||||
xx(LTF_KR, blt, CFKR),
|
||||
xx(LEF_RR, ble, CFRR), // if ((fkb <= fkC) != (A & 1)) then pc++
|
||||
xx(LEF_RK, ble, CFRK),
|
||||
xx(LEF_KR, ble, CFKR),
|
||||
|
||||
// Vector math.
|
||||
xx(NEGV, negv, RVRV), // vA = -vB
|
||||
|
@ -208,14 +208,14 @@ xx(MULVF_RR, mulv, RVRVRV), // vA = vkB * fkC
|
|||
xx(MULVF_RK, mulv, RVRVKV),
|
||||
xx(MULVF_KR, mulv, RVKVRV),
|
||||
xx(LENV, lenv, RFRV), // fA = vB.Length
|
||||
xx(EQV_R, eqv, I8RVRV), // if ((vB == vkC) != A) then pc++ (inexact if A & 32)
|
||||
xx(EQV_K, eqv, I8RVKV),
|
||||
xx(EQV_R, beqv, CVRR), // if ((vB == vkC) != A) then pc++ (inexact if A & 32)
|
||||
xx(EQV_K, beqv, CVRK),
|
||||
|
||||
// Pointer math.
|
||||
xx(ADDA_RR, add, RPRPRI), // pA = pB + dkC
|
||||
xx(ADDA_RK, add, RPRPKI),
|
||||
xx(SUBA, sub, RIRPRP), // dA = pB - pC
|
||||
xx(EQA_R, eq, I8RPRP), // if ((pB == pkC) != A) then pc++
|
||||
xx(EQA_K, eq, I8RPKP),
|
||||
xx(EQA_R, beq, CPRR), // if ((pB == pkC) != A) then pc++
|
||||
xx(EQA_K, beq, CPRK),
|
||||
|
||||
#undef xx
|
||||
|
|
Loading…
Reference in a new issue