#include #include #define nil NULL typedef uint32_t u32; u32 off; char *deststr[16] = { "", "w", "z", "zw", "y", "yw", "yz", "yzw", "x", "xw", "xz", "xzw", "xy", "xyw", "xyz", "xyzw", }; char *flagstr[32] = { "", "[T]", "[D]", "[DT]", "[M]", "[MT]", "[MD]", "[MDT]", "[E]", "[ET]", "[ED]", "[EDT]", "[EM]", "[EMT]", "[EMD]", "[EMDT]", "[I]", "[IT]", "[ID]", "[IDT]", "[IM]", "[IMT]", "[IMD]", "[IMDT]", "[IE]", "[IET]", "[IED]", "[IEDT]", "[IEM]", "[IEMT]", "[IEMD]", "[IEMDT]", }; char *type0str[7] = { "ADD", "SUB", "MADD", "MSUB", "MAX", "MINI", "MUL" }; char *type1str[] = { "MULq", "MAXi", "MULi", "MINIi", "ADDq", "MADDq", "ADDi", "MADDi", "SUBq", "MSUBq", "SUBi", "MSUBi", "ADD", "MADD", "MUL", "MAX", "SUB", "MSUB", "OPMSUB", "MINI" }; char *type2str[] = { "ADDA", "SUBA", "MADDA", "MSUBA", "***", "***", "MULA" }; char *type3str[] = { "ITOF0", "ITOF4", "ITOF12", "ITOF15", "FTOI0", "FTOI4", "FTOI12", "FTOI15", "***", "***", "***", "***", "MULAq", "ABS", "MULAi", "CLIP", "ADDAq", "MADDAq", "ADDAi", "MADDAi", "SUBAq", "MSUBAq", "SUBAi", "MSUBAi", "ADDA", "MADDA", "MULA", "***", "SUBA", "MSUBA", "OPMULA", "NOP" }; int immed; void disupper(u32 inst) { char str[80], *p; u32 bc = inst&3; u32 op0 = (inst>>2) & 0xF; u32 op1 = inst & 0x3F; u32 op2 = (inst>>6) & 0x1F; u32 op3 = (inst & 0x7C0)>>4 | bc; u32 fd = (inst>>6) & 0x1F; u32 fs = (inst>>11) & 0x1F; u32 ft = (inst>>16) & 0x1F; u32 dest = (inst>>21) & 0xF; u32 flags = (inst>>27) & 0x1F; immed = flags >> 4; flags &= 0xF; p = str; switch(op0){ case 0: case 1: case 2: case 3: case 4: case 5: case 6: // bc p += sprintf(p, "%s%c%s.%s", type0str[op0], "xyzw"[bc], flagstr[flags], deststr[dest]); p += sprintf(p, " VF%02d, VF%02d, VF%02d", fd, fs, ft); break; case 7: case 8: case 9: case 0xA: case 0xB: switch(op1){ case 0x1C: case 0x20: case 0x21: case 0x24: case 0x25: // Q p += sprintf(p, "%s%s.%s", type1str[op1-0x1C], flagstr[flags], deststr[dest]); p += sprintf(p, " VF%02d, VF%02d, Q", fd, fs); break; case 0x1D: case 0x1E: case 0x1F: case 0x22: case 0x23: case 0x26: case 0x27: // I p += sprintf(p, "%s%s.%s", type1str[op1-0x1C], flagstr[flags], deststr[dest]); p += sprintf(p, " VF%02d, VF%02d, I", fd, fs); break; case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F: // ft p += sprintf(p, "%s%s.%s", type1str[op1-0x1C], flagstr[flags], deststr[dest]); p += sprintf(p, " VF%02d, VF%02d, VF%02d", fd, fs, ft); break; default: p += sprintf(p, "%08X", inst); } break; case 0xF: switch(op2){ case 0: case 1: case 2: case 3: case 6: p += sprintf(p, "%s%c%s.%s", type2str[op2], "xyzw"[bc], flagstr[flags], deststr[dest]); p += sprintf(p, " ACC, VF%02d, VF%02d", fs, ft); break; case 4: case 5: case 7: case 8: case 9: case 0xA: case 0xB: switch(op3){ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x1D: // t s p += sprintf(p, "%s%s.%s", type3str[op3-0x10], flagstr[flags], deststr[dest]); p += sprintf(p, " VF%02d, VF%02d", ft, fs); break; case 0x1C: case 0x20: case 0x21: case 0x24: case 0x25: // acc s q p += sprintf(p, "%s%s.%s", type3str[op3-0x10], flagstr[flags], deststr[dest]); p += sprintf(p, " ACC, VF%02d, Q", fs); break; case 0x1E: case 0x22: case 0x23: case 0x26: case 0x27: // acc s i p += sprintf(p, "%s%s.%s", type3str[op3-0x10], flagstr[flags], deststr[dest]); p += sprintf(p, " ACC, VF%02d, I", fs); break; case 0x1F: // CLIP p += sprintf(p, "%s%c%s.%s", type3str[op3-0x10], "xyzw"[bc], flagstr[flags], deststr[dest]); p += sprintf(p, " VF%02d, VF%02d", fs, ft); break; case 0x28: case 0x29: case 0x2A: case 0x2C: case 0x2D: case 0x2E: // acc s t p += sprintf(p, "%s%s.%s", type3str[op3-0x10], flagstr[flags], deststr[dest]); p += sprintf(p, " ACC, VF%02d, VF%02d", fs, ft); break; case 0x2F: p += sprintf(p, "%s%s", type3str[op3-0x10], flagstr[flags]); break; default: p += sprintf(p, "%08X", inst); } break; default: p += sprintf(p, "%08X", inst); } break; default: p += sprintf(p, "%08X", inst); break; } printf("%-40s ", str); } #define ADDR(x) ((x) & 0x3FFF) void dislower(u32 inst) { char str[80], *p; u32 op1 = inst & 0x3F; u32 op2 = (inst & 0x7C0)>>4 | (inst&3); u32 fd = (inst>>6) & 0x1F; u32 id = fd; u32 fs = (inst>>11) & 0x1F; u32 is = fs; u32 ft = (inst>>16) & 0x1F; u32 it = ft; u32 dest = (inst>>21) & 0xF; u32 fsf = dest & 3; u32 ftf = (dest>>2) & 3; u32 op = (inst>>25) & 0x7F; u32 imm5 = fd; u32 imm11 = inst & 0x7FF; u32 imm15 = imm11 | dest<<11; u32 imm12 = imm15 & 0xFFF; u32 imm24 = inst & 0xFFFFFF; p = str; if(immed){ printf("LOI %g\n", *(float*)&inst); return; } switch(op){ case 0: p += sprintf(p, "LQ.%s", deststr[dest]); p += sprintf(p, " VF%02d, 0x%X(VI%02d)", ft, imm11, is); break; case 1: p += sprintf(p, "SQ.%s", deststr[dest]); p += sprintf(p, " VF%02d, 0x%X(VI%02d)", fs, imm11, it); break; case 4: p += sprintf(p, "ILW.%s", deststr[dest]); p += sprintf(p, " VI%02d, 0x%X(VI%02d)", it, imm11, is); break; case 5: p += sprintf(p, "ISW.%s", deststr[dest]); p += sprintf(p, " VI%02d, 0x%X(VI%02d)", it, imm11, is); break; case 8: p += sprintf(p, "IADDIU"); p += sprintf(p, " VI%02d, VI%02d, 0x%X", it, is, imm15); break; case 9: p += sprintf(p, "ISUBIU"); p += sprintf(p, " VI%02d, VI%02d, 0x%X", it, is, imm15); break; case 0x10: p += sprintf(p, "FCEQ"); p += sprintf(p, " VI01, 0x%X", imm24); break; case 0x11: p += sprintf(p, "FCSET"); p += sprintf(p, " 0x%X", imm24); break; case 0x12: p += sprintf(p, "FCAND"); p += sprintf(p, " VI01, 0x%X", imm24); break; case 0x13: p += sprintf(p, "FCOR"); p += sprintf(p, " VI01, 0x%X", imm24); break; case 0x14: p += sprintf(p, "FSEQ"); p += sprintf(p, " VI%02d, 0x%X", it, imm12); break; case 0x15: p += sprintf(p, "FSSET"); p += sprintf(p, " 0x%X", imm12); break; case 0x16: p += sprintf(p, "FSAND"); p += sprintf(p, " VI%02d, 0x%X", it, imm12); break; case 0x17: p += sprintf(p, "FSOR"); p += sprintf(p, " VI%02d, 0x%X", it, imm12); break; case 0x18: p += sprintf(p, "FMEQ"); p += sprintf(p, " VI%02d, VI%02d", it, is); break; case 0x1A: p += sprintf(p, "FMAND"); p += sprintf(p, " VI%02d, VI%02d", it, is); break; case 0x1B: p += sprintf(p, "FMOR"); p += sprintf(p, " VI%02d, VI%02d", it, is); break; case 0x1C: p += sprintf(p, "FCGET"); p += sprintf(p, " VI%02d", it); break; case 0x20: p += sprintf(p, "B 0x%X", ADDR(off+8 + imm11*8)); break; case 0x21: p += sprintf(p, "BAL VI%02d, 0x%X", it, ADDR(off+8 + imm11*8)); break; case 0x24: p += sprintf(p, "JR"); p += sprintf(p, " VI%02d", is); break; case 0x25: p += sprintf(p, "JALR"); p += sprintf(p, " VI%02d, VI%02d", it, is); break; case 0x28: p += sprintf(p, "IBEQ"); p += sprintf(p, " VI%02d, VI%02d, 0x%X", it, is, ADDR(off+8 + imm11*8)); break; case 0x29: p += sprintf(p, "IBNE"); p += sprintf(p, " VI%02d, VI%02d, 0x%X", it, is, ADDR(off+8 + imm11*8)); break; case 0x2C: p += sprintf(p, "IBLTZ"); p += sprintf(p, " VI%02d, 0x%X", is, ADDR(off+8 + imm11*8)); break; case 0x2D: p += sprintf(p, "IBGTZ"); p += sprintf(p, " VI%02d, 0x%X", is, ADDR(off+8 + imm11*8)); break; case 0x2E: p += sprintf(p, "IBLEZ"); p += sprintf(p, " VI%02d, 0x%X", is, ADDR(off+8 + imm11*8)); break; case 0x2F: p += sprintf(p, "IBGEZ"); p += sprintf(p, " VI%02d, 0x%X", is, ADDR(off+8 + imm11*8)); break; case 0x40: switch(op1){ case 0x30: p += sprintf(p, "IADD"); p += sprintf(p, " VI%02d, VI%02d, VI%02d", id, is, it); break; case 0x31: p += sprintf(p, "ISUB"); p += sprintf(p, " VI%02d, VI%02d, VI%02d", id, is, it); break; case 0x32: p += sprintf(p, "IADDI"); p += sprintf(p, " VI%02d, VI%02d, 0x%X", it, is, imm5); break; case 0x34: p += sprintf(p, "IAND"); p += sprintf(p, " VI%02d, VI%02d, VI%02d", id, is, it); break; case 0x35: p += sprintf(p, "IOR"); p += sprintf(p, " VI%02d, VI%02d, VI%02d", id, is, it); break; default: switch(op2){ case 0x30: if(ft == 0 && fs == 0) p += sprintf(p, "NOP"); else{ p += sprintf(p, "MOVE.%s", deststr[dest]); p += sprintf(p, " VF%02d, VF%02d", ft, fs); } break; case 0x31: p += sprintf(p, "MR32.%s", deststr[dest]); p += sprintf(p, " VF%02d, VF%02d", ft, fs); break; case 0x34: p += sprintf(p, "LQI.%s", deststr[dest]); p += sprintf(p, " VF%02d, (VI%02d++)", ft, is); break; case 0x35: p += sprintf(p, "SQI.%s", deststr[dest]); p += sprintf(p, " VF%02d, (VI%02d++)", fs, it); break; case 0x36: p += sprintf(p, "LQD.%s", deststr[dest]); p += sprintf(p, " VF%02d, (--VI%02d)", ft, is); break; case 0x37: p += sprintf(p, "SQD.%s", deststr[dest]); p += sprintf(p, " VF%02d, (--VI%02d)", fs, it); break; case 0x38: p += sprintf(p, "DIV"); p += sprintf(p, " Q, VF%02d%c, VF%02d%c", fs, "xyzw"[fsf], ft, "xyzw"[ftf]); break; case 0x39: p += sprintf(p, "SQRT"); p += sprintf(p, " Q, VF%02d%c", ft, "xyzw"[ftf]); break; case 0x3A: p += sprintf(p, "RSQRT"); p += sprintf(p, " Q, VF%02d%c, VF%02d%c", fs, "xyzw"[fsf], ft, "xyzw"[ftf]); break; case 0x3B: p += sprintf(p, "WAITQ"); break; case 0x3C: p += sprintf(p, "MTIR"); p += sprintf(p, " VI%02d, VF%02d%c", it, fs, "xyzw"[fsf]); break; case 0x3D: p += sprintf(p, "MFIR.%s", deststr[dest]); p += sprintf(p, " VF%02d, VI%02d", ft, is); break; case 0x3E: p += sprintf(p, "ILWR.%s", deststr[dest]); p += sprintf(p, " VI%02d, (VI%02d)", it, is); break; case 0x3F: p += sprintf(p, "ISWR.%s", deststr[dest]); p += sprintf(p, " VI%02d, (VI%02d)", it, is); break; case 0x40: p += sprintf(p, "RNEXT.%s", deststr[dest]); p += sprintf(p, " VF%02d, R", ft); break; case 0x41: p += sprintf(p, "RGET.%s", deststr[dest]); p += sprintf(p, " VF%02d, R", ft); break; case 0x42: p += sprintf(p, "RINIT"); p += sprintf(p, " R, VF%02d%c", fs, "xyzw"[fsf]); break; case 0x43: p += sprintf(p, "RXOR"); p += sprintf(p, " R, VF%02d%c", fs, "xyzw"[fsf]); break; case 0x64: p += sprintf(p, "MFP.%s", deststr[dest]); p += sprintf(p, " VF%02d, P", ft); break; case 0x68: p += sprintf(p, "XTOP"); p += sprintf(p, " VI%02d", it); break; case 0x69: p += sprintf(p, "XITOP"); p += sprintf(p, " VI%02d", it); break; case 0x6C: p += sprintf(p, "XGKICK"); p += sprintf(p, " VI%02d", is); break; case 0x70: p += sprintf(p, "ESADD"); p += sprintf(p, " P, VF%02d", fs); break; case 0x71: p += sprintf(p, "ERSADD"); p += sprintf(p, " P, VF%02d", fs); break; case 0x72: p += sprintf(p, "ELENG"); p += sprintf(p, " P, VF%02d", fs); break; case 0x73: p += sprintf(p, "ERLENG"); p += sprintf(p, " P, VF%02d", fs); break; case 0x74: p += sprintf(p, "EATANxy"); p += sprintf(p, " P, VF%02d", fs); break; case 0x75: p += sprintf(p, "EATANxz"); p += sprintf(p, " P, VF%02d", fs); break; case 0x76: p += sprintf(p, "ESUM"); p += sprintf(p, " P, VF%02d", fs); break; case 0x78: p += sprintf(p, "ESQRT"); p += sprintf(p, " P, VF%02d%c", fs, "xyzw"[fsf]); break; case 0x79: p += sprintf(p, "ERSQRT"); p += sprintf(p, " P, VF%02d%c", fs, "xyzw"[fsf]); break; case 0x7A: p += sprintf(p, "ERCPR"); p += sprintf(p, " P, VF%02d%c", fs, "xyzw"[fsf]); break; case 0x7B: p += sprintf(p, "WAITP"); break; case 0x7C: p += sprintf(p, "ESIN"); p += sprintf(p, " P, VF%02d%c", fs, "xyzw"[fsf]); break; case 0x7D: p += sprintf(p, "EATAN"); p += sprintf(p, " P, VF%02d%c", fs, "xyzw"[fsf]); break; case 0x7E: p += sprintf(p, "EEXP"); p += sprintf(p, " P, VF%02d%c", fs, "xyzw"[fsf]); break; default: fprintf(stderr, "unknown inst at %X\n", off); p += sprintf(p, "%08X", inst); break; } } break; default: fprintf(stderr, "unknown inst at %X\n", off); p += sprintf(p, "%08X", inst); break; } printf("%s\n", str); } int main(int argc, char *argv[]) { FILE *f; u32 inst[2]; if(argc < 2){ fprintf(stderr, "not enough arguments\n"); return 1; } f = fopen(argv[1], "rb"); if(f == nil){ fprintf(stderr, "couldn't open %s\n", argv[1]); return 1; } off = 0; while(fread(inst, 4, 2, f) == 2){ printf("%04X: ", off); disupper(inst[1]); dislower(inst[0]); off += 8; } return 0; }