* 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.
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
};
// {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"},
// 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)
{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
{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)
}
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)))
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);
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;
}