From: kub Date: Mon, 14 Dec 2020 20:14:13 +0000 (+0100) Subject: improve mips disassembler to handle most of N32 code X-Git-Tag: v2.00~632 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=70e9ca7191b52818a1d09ac79ca4f69aff8f5437;p=picodrive.git improve mips disassembler to handle most of N32 code --- diff --git a/platform/common/dismips.c b/platform/common/dismips.c index d855ad6b..b3d90015 100644 --- a/platform/common/dismips.c +++ b/platform/common/dismips.c @@ -6,8 +6,8 @@ * See COPYING file in the top-level directory. */ -// unimplemented insns: MOV[FT], SYSCALL, BREAK, SYNC, SYNCI, T*, SDBBP, RDHWR, -// CACHE, PREF, LWC*/LDC*, SWC*/SDC*, and all of COP* (fpu, mmu, irq, exc, ...) +// unimplemented insns: SYNC, CACHE, PREF, +// MOV[FT], LWC*/LDC*, SWC*/SDC*, and all of COP* (fpu, mmu, irq, exc, ...) // unimplemented variants of insns: EHB, SSNOP (both SLL zero), JALR.HB, JR.HB // however, it's certainly good enough for anything picodrive DRC throws at it. @@ -56,15 +56,17 @@ static char *const register_names[32] = { enum insn_type { - REG_DTS, REG_TS, // 3, 2, or 1 regs + REG_DST, REG_ST, REG_TD, // 3, 2, or 1 regs REG_DS, REG_DT, REG_D, REG_S, S_IMM_DT, // 2 regs with shift amount F_IMM_TS, // 2 regs with bitfield spec B_IMM_S, B_IMM_TS, // pc-relative branches with 1 or 2 regs + T_IMM_S, // trap insns with immediate J_IMM, // region-relative jump A_IMM_TS, // arithmetic immediate with 2 regs L_IMM_T, L_IMM_TS, // logical immediate with 1 or 2 regs - M_IMM_TS, // memory indexed with 2 regs + M_IMM_TS, M_IMM_S, // memory indexed with 2 regs + SB_CODE, // code parameter (syscall, break, sdbbp) SR_BIT = 0x80 // shift right with R-bit }; @@ -83,51 +85,51 @@ static const struct insn special_insns[] = { // {0x01, , "movf\0movt"}, {0x02, S_IMM_DT|SR_BIT, "srl\0rotr"}, {0x03, S_IMM_DT, "sra"}, - {0x04, REG_DTS, "sllv"}, - {0x06, REG_DTS|SR_BIT, "srlv\0rotrv"}, - {0x07, REG_DTS, "srav"}, + {0x04, REG_DST, "sllv"}, + {0x06, REG_DST|SR_BIT, "srlv\0rotrv"}, + {0x07, REG_DST, "srav"}, {0x08, REG_S, "jr"}, {0x09, REG_DS, "jalr"}, - {0x0a, REG_DTS, "movz"}, - {0x0b, REG_DTS, "movn"}, -// {0x0c, , "syscall"}, -// {0x0d, , "break"}, + {0x0a, REG_DST, "movz"}, + {0x0b, REG_DST, "movn"}, + {0x0c, SB_CODE, "syscall"}, + {0x0d, SB_CODE, "break"}, // {0x0f, , "sync"}, {0x10, REG_D, "mfhi"}, {0x11, REG_S, "mthi"}, {0x12, REG_D, "mflo"}, {0x13, REG_S, "mtlo"}, - {0x14, REG_DTS, "dsllv"}, - {0x16, REG_DTS|SR_BIT, "dsrlv\0drotrv"}, - {0x17, REG_DTS, "dsrav"}, - {0x18, REG_TS, "mult"}, - {0x19, REG_TS, "multu"}, - {0x1A, REG_TS, "div"}, - {0x1B, REG_TS, "divu"}, - {0x1C, REG_TS, "dmult"}, - {0x1D, REG_TS, "dmultu"}, - {0x1E, REG_TS, "ddiv"}, - {0x1F, REG_TS, "ddivu"}, - {0x20, REG_DTS, "add"}, - {0x21, REG_DTS, "addu"}, - {0x22, REG_DTS, "sub"}, - {0x23, REG_DTS, "subu"}, - {0x24, REG_DTS, "and"}, - {0x25, REG_DTS, "or"}, - {0x26, REG_DTS, "xor"}, - {0x27, REG_DTS, "nor"}, - {0x2A, REG_DTS, "slt"}, - {0x2B, REG_DTS, "sltu"}, - {0x2C, REG_DTS, "dadd"}, - {0x2D, REG_DTS, "daddu"}, - {0x2E, REG_DTS, "dsub"}, - {0x2F, REG_DTS, "dsubu"}, -// {0x30, REG_TS, "tge" }, -// {0x31, REG_TS, "tgeu" }, -// {0x32, REG_TS, "tlt" }, -// {0x33, REG_TS, "tltu" }, -// {0x34, REG_TS, "teq" }, -// {0x36, REG_TS, "tne" }, + {0x14, REG_DST, "dsllv"}, + {0x16, REG_DST|SR_BIT, "dsrlv\0drotrv"}, + {0x17, REG_DST, "dsrav"}, + {0x18, REG_ST, "mult"}, + {0x19, REG_ST, "multu"}, + {0x1A, REG_ST, "div"}, + {0x1B, REG_ST, "divu"}, + {0x1C, REG_ST, "dmult"}, + {0x1D, REG_ST, "dmultu"}, + {0x1E, REG_ST, "ddiv"}, + {0x1F, REG_ST, "ddivu"}, + {0x20, REG_DST, "add"}, + {0x21, REG_DST, "addu"}, + {0x22, REG_DST, "sub"}, + {0x23, REG_DST, "subu"}, + {0x24, REG_DST, "and"}, + {0x25, REG_DST, "or"}, + {0x26, REG_DST, "xor"}, + {0x27, REG_DST, "nor"}, + {0x2A, REG_DST, "slt"}, + {0x2B, REG_DST, "sltu"}, + {0x2C, REG_DST, "dadd"}, + {0x2D, REG_DST, "daddu"}, + {0x2E, REG_DST, "dsub"}, + {0x2F, REG_DST, "dsubu"}, + {0x30, REG_ST, "tge" }, + {0x31, REG_ST, "tgeu" }, + {0x32, REG_ST, "tlt" }, + {0x33, REG_ST, "tltu" }, + {0x34, REG_ST, "teq" }, + {0x36, REG_ST, "tne" }, {0x38, S_IMM_DT, "dsll"}, {0x3A, S_IMM_DT|SR_BIT, "dsrl\0drotrv"}, {0x3B, S_IMM_DT, "dsra"}, @@ -139,16 +141,16 @@ static const struct insn special_insns[] = { // instructions with opcode SPECIAL2 (R-type) #define OP_SPECIAL2 0x1C static const struct insn special2_insns[] = { - {0x00, REG_TS, "madd" }, - {0x01, REG_TS, "maddu" }, - {0x02, REG_TS, "mul" }, - {0x04, REG_TS, "msub" }, - {0x05, REG_TS, "msubu" }, + {0x00, REG_ST, "madd" }, + {0x01, REG_ST, "maddu" }, + {0x02, REG_ST, "mul" }, + {0x04, REG_ST, "msub" }, + {0x05, REG_ST, "msubu" }, {0x20, REG_DS, "clz" }, {0x21, REG_DS, "clo" }, {0x24, REG_DS, "dclz" }, {0x25, REG_DS, "dclo" }, -// {0x37, , "sdbbp" }, + {0x37, SB_CODE, "sdbbp" }, }; // instructions with opcode SPECIAL3 (R-type) @@ -162,7 +164,7 @@ static const struct insn special3_insns[] = { {0x05, F_IMM_TS, "dinsm" }, {0x06, F_IMM_TS, "dinsu" }, {0x07, F_IMM_TS, "dins" }, -// {0x3b, , "rdhwr" }, + {0x3b, REG_TD, "rdhwr" }, }; // instruction with opcode SPECIAL3 and function *BSHFL @@ -185,18 +187,17 @@ static const struct insn regimm_insns[] = { {0x01, B_IMM_S, "bgez"}, {0x02, B_IMM_S, "bltzl"}, {0x03, B_IMM_S, "bgezl"}, -// {0x08, , "tgei"}, -// {0x09, , "tgeiu"}, -// {0x0a, , "tlti"}, -// {0x0b, , "tltiu"}, -// {0x0c, , "teqi"}, -// {0x0e, , "tnei"}, + {0x08, T_IMM_S, "tgei"}, + {0x09, T_IMM_S, "tgeiu"}, + {0x0a, T_IMM_S, "tlti"}, + {0x0b, T_IMM_S, "tltiu"}, + {0x0c, T_IMM_S, "teqi"}, + {0x0e, T_IMM_S, "tnei"}, {0x10, B_IMM_S, "bltzal"}, {0x11, B_IMM_S, "bgezal"}, {0x12, B_IMM_S, "bltzall"}, {0x13, B_IMM_S, "bgezall"}, - {0x13, B_IMM_S, "bgezall"}, -// {0x1f, , "synci" }, + {0x1f, M_IMM_S, "synci" }, }; // instructions with other opcodes (I-type) @@ -337,7 +338,7 @@ int dismips(uintptr_t pc, uint32_t insn, char *buf, size_t buflen, unsigned long } switch (pi->type & ~SR_BIT) { - case REG_DTS: + case REG_DST: if ((insn & 0x3f) == 0x25 /*OR*/ && (insn & 0x1f0000) == 0 /*zero*/) snprintf(buf, buflen, "move %s, %s", rd, rs); else if ((pi->type & SR_BIT) && (insn & (1<<6))) @@ -345,8 +346,14 @@ int dismips(uintptr_t pc, uint32_t insn, char *buf, size_t buflen, unsigned long else snprintf(buf, buflen, "%s %s, %s, %s", pi->name, rd, rs, rt); break; - case REG_TS: - snprintf(buf, buflen, "%s %s, %s", pi->name, rs, rt); + case REG_ST: + if ((insn & 0x38) == 0x30 /*T..*/) + snprintf(buf, buflen, "%s %s, %s (code %d)", pi->name, rs, rt, (insn>>6) & 0x3ff); + else + snprintf(buf, buflen, "%s %s, %s", pi->name, rs, rt); + break; + case REG_TD: + snprintf(buf, buflen, "%s %s, %s", pi->name, rt, rd); break; case REG_DS: snprintf(buf, buflen, "%s %s, %s", pi->name, rd, rs); @@ -406,6 +413,15 @@ int dismips(uintptr_t pc, uint32_t insn, char *buf, size_t buflen, unsigned long case M_IMM_TS: snprintf(buf, buflen, "%s %s, %d(%s)", pi->name, rt, imm, rs); break; + case M_IMM_S: + snprintf(buf, buflen, "%s %d(%s)", pi->name, imm, rs); + break; + case T_IMM_S: + snprintf(buf, buflen, "%s %s, %d", pi->name, rs, imm); + break; + case SB_CODE: + snprintf(buf, buflen, "%s %d", pi->name, (insn>>6) & 0xfffff); + break; } return 1; }