mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
improve mips disassembler to handle most of N32 code
This commit is contained in:
parent
7c5227a490
commit
70e9ca7191
1 changed files with 76 additions and 60 deletions
|
@ -6,8 +6,8 @@
|
||||||
* See COPYING file in the top-level directory.
|
* See COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// unimplemented insns: MOV[FT], SYSCALL, BREAK, SYNC, SYNCI, T*, SDBBP, RDHWR,
|
// unimplemented insns: SYNC, CACHE, PREF,
|
||||||
// CACHE, PREF, LWC*/LDC*, SWC*/SDC*, and all of COP* (fpu, mmu, irq, exc, ...)
|
// 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
|
// 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.
|
// 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 {
|
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,
|
REG_DS, REG_DT, REG_D, REG_S,
|
||||||
S_IMM_DT, // 2 regs with shift amount
|
S_IMM_DT, // 2 regs with shift amount
|
||||||
F_IMM_TS, // 2 regs with bitfield spec
|
F_IMM_TS, // 2 regs with bitfield spec
|
||||||
B_IMM_S, B_IMM_TS, // pc-relative branches with 1 or 2 regs
|
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
|
J_IMM, // region-relative jump
|
||||||
A_IMM_TS, // arithmetic immediate with 2 regs
|
A_IMM_TS, // arithmetic immediate with 2 regs
|
||||||
L_IMM_T, L_IMM_TS, // logical immediate with 1 or 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
|
SR_BIT = 0x80 // shift right with R-bit
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,51 +85,51 @@ static const struct insn special_insns[] = {
|
||||||
// {0x01, , "movf\0movt"},
|
// {0x01, , "movf\0movt"},
|
||||||
{0x02, S_IMM_DT|SR_BIT, "srl\0rotr"},
|
{0x02, S_IMM_DT|SR_BIT, "srl\0rotr"},
|
||||||
{0x03, S_IMM_DT, "sra"},
|
{0x03, S_IMM_DT, "sra"},
|
||||||
{0x04, REG_DTS, "sllv"},
|
{0x04, REG_DST, "sllv"},
|
||||||
{0x06, REG_DTS|SR_BIT, "srlv\0rotrv"},
|
{0x06, REG_DST|SR_BIT, "srlv\0rotrv"},
|
||||||
{0x07, REG_DTS, "srav"},
|
{0x07, REG_DST, "srav"},
|
||||||
{0x08, REG_S, "jr"},
|
{0x08, REG_S, "jr"},
|
||||||
{0x09, REG_DS, "jalr"},
|
{0x09, REG_DS, "jalr"},
|
||||||
{0x0a, REG_DTS, "movz"},
|
{0x0a, REG_DST, "movz"},
|
||||||
{0x0b, REG_DTS, "movn"},
|
{0x0b, REG_DST, "movn"},
|
||||||
// {0x0c, , "syscall"},
|
{0x0c, SB_CODE, "syscall"},
|
||||||
// {0x0d, , "break"},
|
{0x0d, SB_CODE, "break"},
|
||||||
// {0x0f, , "sync"},
|
// {0x0f, , "sync"},
|
||||||
{0x10, REG_D, "mfhi"},
|
{0x10, REG_D, "mfhi"},
|
||||||
{0x11, REG_S, "mthi"},
|
{0x11, REG_S, "mthi"},
|
||||||
{0x12, REG_D, "mflo"},
|
{0x12, REG_D, "mflo"},
|
||||||
{0x13, REG_S, "mtlo"},
|
{0x13, REG_S, "mtlo"},
|
||||||
{0x14, REG_DTS, "dsllv"},
|
{0x14, REG_DST, "dsllv"},
|
||||||
{0x16, REG_DTS|SR_BIT, "dsrlv\0drotrv"},
|
{0x16, REG_DST|SR_BIT, "dsrlv\0drotrv"},
|
||||||
{0x17, REG_DTS, "dsrav"},
|
{0x17, REG_DST, "dsrav"},
|
||||||
{0x18, REG_TS, "mult"},
|
{0x18, REG_ST, "mult"},
|
||||||
{0x19, REG_TS, "multu"},
|
{0x19, REG_ST, "multu"},
|
||||||
{0x1A, REG_TS, "div"},
|
{0x1A, REG_ST, "div"},
|
||||||
{0x1B, REG_TS, "divu"},
|
{0x1B, REG_ST, "divu"},
|
||||||
{0x1C, REG_TS, "dmult"},
|
{0x1C, REG_ST, "dmult"},
|
||||||
{0x1D, REG_TS, "dmultu"},
|
{0x1D, REG_ST, "dmultu"},
|
||||||
{0x1E, REG_TS, "ddiv"},
|
{0x1E, REG_ST, "ddiv"},
|
||||||
{0x1F, REG_TS, "ddivu"},
|
{0x1F, REG_ST, "ddivu"},
|
||||||
{0x20, REG_DTS, "add"},
|
{0x20, REG_DST, "add"},
|
||||||
{0x21, REG_DTS, "addu"},
|
{0x21, REG_DST, "addu"},
|
||||||
{0x22, REG_DTS, "sub"},
|
{0x22, REG_DST, "sub"},
|
||||||
{0x23, REG_DTS, "subu"},
|
{0x23, REG_DST, "subu"},
|
||||||
{0x24, REG_DTS, "and"},
|
{0x24, REG_DST, "and"},
|
||||||
{0x25, REG_DTS, "or"},
|
{0x25, REG_DST, "or"},
|
||||||
{0x26, REG_DTS, "xor"},
|
{0x26, REG_DST, "xor"},
|
||||||
{0x27, REG_DTS, "nor"},
|
{0x27, REG_DST, "nor"},
|
||||||
{0x2A, REG_DTS, "slt"},
|
{0x2A, REG_DST, "slt"},
|
||||||
{0x2B, REG_DTS, "sltu"},
|
{0x2B, REG_DST, "sltu"},
|
||||||
{0x2C, REG_DTS, "dadd"},
|
{0x2C, REG_DST, "dadd"},
|
||||||
{0x2D, REG_DTS, "daddu"},
|
{0x2D, REG_DST, "daddu"},
|
||||||
{0x2E, REG_DTS, "dsub"},
|
{0x2E, REG_DST, "dsub"},
|
||||||
{0x2F, REG_DTS, "dsubu"},
|
{0x2F, REG_DST, "dsubu"},
|
||||||
// {0x30, REG_TS, "tge" },
|
{0x30, REG_ST, "tge" },
|
||||||
// {0x31, REG_TS, "tgeu" },
|
{0x31, REG_ST, "tgeu" },
|
||||||
// {0x32, REG_TS, "tlt" },
|
{0x32, REG_ST, "tlt" },
|
||||||
// {0x33, REG_TS, "tltu" },
|
{0x33, REG_ST, "tltu" },
|
||||||
// {0x34, REG_TS, "teq" },
|
{0x34, REG_ST, "teq" },
|
||||||
// {0x36, REG_TS, "tne" },
|
{0x36, REG_ST, "tne" },
|
||||||
{0x38, S_IMM_DT, "dsll"},
|
{0x38, S_IMM_DT, "dsll"},
|
||||||
{0x3A, S_IMM_DT|SR_BIT, "dsrl\0drotrv"},
|
{0x3A, S_IMM_DT|SR_BIT, "dsrl\0drotrv"},
|
||||||
{0x3B, S_IMM_DT, "dsra"},
|
{0x3B, S_IMM_DT, "dsra"},
|
||||||
|
@ -139,16 +141,16 @@ static const struct insn special_insns[] = {
|
||||||
// instructions with opcode SPECIAL2 (R-type)
|
// instructions with opcode SPECIAL2 (R-type)
|
||||||
#define OP_SPECIAL2 0x1C
|
#define OP_SPECIAL2 0x1C
|
||||||
static const struct insn special2_insns[] = {
|
static const struct insn special2_insns[] = {
|
||||||
{0x00, REG_TS, "madd" },
|
{0x00, REG_ST, "madd" },
|
||||||
{0x01, REG_TS, "maddu" },
|
{0x01, REG_ST, "maddu" },
|
||||||
{0x02, REG_TS, "mul" },
|
{0x02, REG_ST, "mul" },
|
||||||
{0x04, REG_TS, "msub" },
|
{0x04, REG_ST, "msub" },
|
||||||
{0x05, REG_TS, "msubu" },
|
{0x05, REG_ST, "msubu" },
|
||||||
{0x20, REG_DS, "clz" },
|
{0x20, REG_DS, "clz" },
|
||||||
{0x21, REG_DS, "clo" },
|
{0x21, REG_DS, "clo" },
|
||||||
{0x24, REG_DS, "dclz" },
|
{0x24, REG_DS, "dclz" },
|
||||||
{0x25, REG_DS, "dclo" },
|
{0x25, REG_DS, "dclo" },
|
||||||
// {0x37, , "sdbbp" },
|
{0x37, SB_CODE, "sdbbp" },
|
||||||
};
|
};
|
||||||
|
|
||||||
// instructions with opcode SPECIAL3 (R-type)
|
// instructions with opcode SPECIAL3 (R-type)
|
||||||
|
@ -162,7 +164,7 @@ static const struct insn special3_insns[] = {
|
||||||
{0x05, F_IMM_TS, "dinsm" },
|
{0x05, F_IMM_TS, "dinsm" },
|
||||||
{0x06, F_IMM_TS, "dinsu" },
|
{0x06, F_IMM_TS, "dinsu" },
|
||||||
{0x07, F_IMM_TS, "dins" },
|
{0x07, F_IMM_TS, "dins" },
|
||||||
// {0x3b, , "rdhwr" },
|
{0x3b, REG_TD, "rdhwr" },
|
||||||
};
|
};
|
||||||
|
|
||||||
// instruction with opcode SPECIAL3 and function *BSHFL
|
// instruction with opcode SPECIAL3 and function *BSHFL
|
||||||
|
@ -185,18 +187,17 @@ static const struct insn regimm_insns[] = {
|
||||||
{0x01, B_IMM_S, "bgez"},
|
{0x01, B_IMM_S, "bgez"},
|
||||||
{0x02, B_IMM_S, "bltzl"},
|
{0x02, B_IMM_S, "bltzl"},
|
||||||
{0x03, B_IMM_S, "bgezl"},
|
{0x03, B_IMM_S, "bgezl"},
|
||||||
// {0x08, , "tgei"},
|
{0x08, T_IMM_S, "tgei"},
|
||||||
// {0x09, , "tgeiu"},
|
{0x09, T_IMM_S, "tgeiu"},
|
||||||
// {0x0a, , "tlti"},
|
{0x0a, T_IMM_S, "tlti"},
|
||||||
// {0x0b, , "tltiu"},
|
{0x0b, T_IMM_S, "tltiu"},
|
||||||
// {0x0c, , "teqi"},
|
{0x0c, T_IMM_S, "teqi"},
|
||||||
// {0x0e, , "tnei"},
|
{0x0e, T_IMM_S, "tnei"},
|
||||||
{0x10, B_IMM_S, "bltzal"},
|
{0x10, B_IMM_S, "bltzal"},
|
||||||
{0x11, B_IMM_S, "bgezal"},
|
{0x11, B_IMM_S, "bgezal"},
|
||||||
{0x12, B_IMM_S, "bltzall"},
|
{0x12, B_IMM_S, "bltzall"},
|
||||||
{0x13, B_IMM_S, "bgezall"},
|
{0x13, B_IMM_S, "bgezall"},
|
||||||
{0x13, B_IMM_S, "bgezall"},
|
{0x1f, M_IMM_S, "synci" },
|
||||||
// {0x1f, , "synci" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// instructions with other opcodes (I-type)
|
// 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) {
|
switch (pi->type & ~SR_BIT) {
|
||||||
case REG_DTS:
|
case REG_DST:
|
||||||
if ((insn & 0x3f) == 0x25 /*OR*/ && (insn & 0x1f0000) == 0 /*zero*/)
|
if ((insn & 0x3f) == 0x25 /*OR*/ && (insn & 0x1f0000) == 0 /*zero*/)
|
||||||
snprintf(buf, buflen, "move %s, %s", rd, rs);
|
snprintf(buf, buflen, "move %s, %s", rd, rs);
|
||||||
else if ((pi->type & SR_BIT) && (insn & (1<<6)))
|
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
|
else
|
||||||
snprintf(buf, buflen, "%s %s, %s, %s", pi->name, rd, rs, rt);
|
snprintf(buf, buflen, "%s %s, %s, %s", pi->name, rd, rs, rt);
|
||||||
break;
|
break;
|
||||||
case REG_TS:
|
case REG_ST:
|
||||||
snprintf(buf, buflen, "%s %s, %s", pi->name, rs, rt);
|
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;
|
break;
|
||||||
case REG_DS:
|
case REG_DS:
|
||||||
snprintf(buf, buflen, "%s %s, %s", pi->name, rd, rs);
|
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:
|
case M_IMM_TS:
|
||||||
snprintf(buf, buflen, "%s %s, %d(%s)", pi->name, rt, imm, rs);
|
snprintf(buf, buflen, "%s %s, %d(%s)", pi->name, rt, imm, rs);
|
||||||
break;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue