From 5d2cbf4ecb1752f0cf10b39bee21c1921a3682f1 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 13 Mar 2015 23:14:42 -0500 Subject: [PATCH] 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. --- src/zscript/vm.h | 2 ++ src/zscript/vmdisasm.cpp | 65 +++++++++++++++++++++++++++++++++++----- src/zscript/vmops.h | 52 ++++++++++++++++---------------- 3 files changed, 85 insertions(+), 34 deletions(-) diff --git a/src/zscript/vm.h b/src/zscript/vm.h index 4bc8f01c0..06f289bb4 100644 --- a/src/zscript/vm.h +++ b/src/zscript/vm.h @@ -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, diff --git a/src/zscript/vmdisasm.cpp b/src/zscript/vmdisasm.cpp index e003d1595..2509b60a9 100644 --- a/src/zscript/vmdisasm.cpp +++ b/src/zscript/vmdisasm.cpp @@ -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; } diff --git a/src/zscript/vmops.h b/src/zscript/vmops.h index 125e5463d..998a4eb0c 100644 --- a/src/zscript/vmops.h +++ b/src/zscript/vmops.h @@ -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