1*219b2ee8SDavid du Colombier #include <u.h> 2*219b2ee8SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <bio.h> 4*219b2ee8SDavid du Colombier #include <mach.h> 5*219b2ee8SDavid du Colombier 6*219b2ee8SDavid du Colombier /* mips native disassembler */ 7*219b2ee8SDavid du Colombier 8*219b2ee8SDavid du Colombier typedef struct { 9*219b2ee8SDavid du Colombier long addr; /* pc of instr */ 10*219b2ee8SDavid du Colombier uchar op; /* bits 31-26 */ 11*219b2ee8SDavid du Colombier uchar rs; /* bits 25-21 */ 12*219b2ee8SDavid du Colombier uchar rt; /* bits 20-16 */ 13*219b2ee8SDavid du Colombier uchar rd; /* bits 15-11 */ 14*219b2ee8SDavid du Colombier uchar sa; /* bits 10-6 */ 15*219b2ee8SDavid du Colombier uchar function; /* bits 5-0 */ 16*219b2ee8SDavid du Colombier long immediate; /* bits 15-0 */ 17*219b2ee8SDavid du Colombier ulong cofun; /* bits 24-0 */ 18*219b2ee8SDavid du Colombier ulong target; /* bits 25-0 */ 19*219b2ee8SDavid du Colombier long w0; 20*219b2ee8SDavid du Colombier char *curr; /* current fill point */ 21*219b2ee8SDavid du Colombier char *end; /* end of buffer */ 22*219b2ee8SDavid du Colombier char *err; 23*219b2ee8SDavid du Colombier } Instr; 24*219b2ee8SDavid du Colombier 25*219b2ee8SDavid du Colombier typedef struct { 26*219b2ee8SDavid du Colombier char *mnemonic; 27*219b2ee8SDavid du Colombier char *mipsco; 28*219b2ee8SDavid du Colombier } Opcode; 29*219b2ee8SDavid du Colombier 30*219b2ee8SDavid du Colombier static char mipscoload[] = "r%t,%l"; 31*219b2ee8SDavid du Colombier static char mipscoalui[] = "r%t,r%s,%i"; 32*219b2ee8SDavid du Colombier static char mipscoalu3op[] = "r%d,r%s,r%t"; 33*219b2ee8SDavid du Colombier static char mipscoboc[] = "r%s,r%t,%b"; 34*219b2ee8SDavid du Colombier static char mipscoboc0[] = "r%s,%b"; 35*219b2ee8SDavid du Colombier static char mipscorsrt[] = "r%s,r%t"; 36*219b2ee8SDavid du Colombier static char mipscorsi[] = "r%s,%i"; 37*219b2ee8SDavid du Colombier static char mipscoxxx[] = "%w"; 38*219b2ee8SDavid du Colombier static char mipscofp3[] = "f%a,f%d,f%t"; /* fd,fs,ft */ 39*219b2ee8SDavid du Colombier static char mipscofp2[] = "f%a,f%d"; /* fd,fs */ 40*219b2ee8SDavid du Colombier static char mipscofpc[] = "f%d,f%t"; /* fs,ft */ 41*219b2ee8SDavid du Colombier 42*219b2ee8SDavid du Colombier static Opcode opcodes[64] = { 43*219b2ee8SDavid du Colombier 0, 0, 44*219b2ee8SDavid du Colombier 0, 0, 45*219b2ee8SDavid du Colombier "j", "%j", 46*219b2ee8SDavid du Colombier "jal", "%j", 47*219b2ee8SDavid du Colombier "beq", mipscoboc, 48*219b2ee8SDavid du Colombier "bne", mipscoboc, 49*219b2ee8SDavid du Colombier "blez", mipscoboc0, 50*219b2ee8SDavid du Colombier "bgtz", mipscoboc0, 51*219b2ee8SDavid du Colombier "addi", mipscoalui, 52*219b2ee8SDavid du Colombier "addiu", mipscoalui, 53*219b2ee8SDavid du Colombier "slti", mipscoalui, 54*219b2ee8SDavid du Colombier "sltiu", mipscoalui, 55*219b2ee8SDavid du Colombier "andi", mipscoalui, 56*219b2ee8SDavid du Colombier "ori", mipscoalui, 57*219b2ee8SDavid du Colombier "xori", mipscoalui, 58*219b2ee8SDavid du Colombier "lui", "r%t,%u", 59*219b2ee8SDavid du Colombier "cop0", 0, 60*219b2ee8SDavid du Colombier "cop1", 0, 61*219b2ee8SDavid du Colombier "cop2", 0, 62*219b2ee8SDavid du Colombier "cop3", 0, 63*219b2ee8SDavid du Colombier "beql", mipscoboc, 64*219b2ee8SDavid du Colombier "bnel", mipscoboc, 65*219b2ee8SDavid du Colombier "blezl", mipscoboc0, 66*219b2ee8SDavid du Colombier "bgtzl", mipscoboc0, 67*219b2ee8SDavid du Colombier "instr18", mipscoxxx, 68*219b2ee8SDavid du Colombier "instr19", mipscoxxx, 69*219b2ee8SDavid du Colombier "instr1A", mipscoxxx, 70*219b2ee8SDavid du Colombier "instr1B", mipscoxxx, 71*219b2ee8SDavid du Colombier "instr1C", mipscoxxx, 72*219b2ee8SDavid du Colombier "instr1D", mipscoxxx, 73*219b2ee8SDavid du Colombier "instr1E", mipscoxxx, 74*219b2ee8SDavid du Colombier "instr1F", mipscoxxx, 75*219b2ee8SDavid du Colombier "lb", mipscoload, 76*219b2ee8SDavid du Colombier "lh", mipscoload, 77*219b2ee8SDavid du Colombier "lwl", mipscoload, 78*219b2ee8SDavid du Colombier "lw", mipscoload, 79*219b2ee8SDavid du Colombier "lbu", mipscoload, 80*219b2ee8SDavid du Colombier "lhu", mipscoload, 81*219b2ee8SDavid du Colombier "lwr", mipscoload, 82*219b2ee8SDavid du Colombier "instr27", mipscoxxx, 83*219b2ee8SDavid du Colombier "sb", mipscoload, 84*219b2ee8SDavid du Colombier "sh", mipscoload, 85*219b2ee8SDavid du Colombier "swl", mipscoload, 86*219b2ee8SDavid du Colombier "sw", mipscoload, 87*219b2ee8SDavid du Colombier "instr2C", mipscoxxx, 88*219b2ee8SDavid du Colombier "instr2D", mipscoxxx, 89*219b2ee8SDavid du Colombier "swr", mipscoload, 90*219b2ee8SDavid du Colombier "cache", "", 91*219b2ee8SDavid du Colombier "ll", mipscoload, 92*219b2ee8SDavid du Colombier "lwc1", mipscoload, 93*219b2ee8SDavid du Colombier "lwc2", mipscoload, 94*219b2ee8SDavid du Colombier "lwc3", mipscoload, 95*219b2ee8SDavid du Colombier "instr34", mipscoxxx, 96*219b2ee8SDavid du Colombier "ld", mipscoload, 97*219b2ee8SDavid du Colombier "ld", mipscoload, 98*219b2ee8SDavid du Colombier "ld", mipscoload, 99*219b2ee8SDavid du Colombier "sc", mipscoload, 100*219b2ee8SDavid du Colombier "swc1", mipscoload, 101*219b2ee8SDavid du Colombier "swc2", mipscoload, 102*219b2ee8SDavid du Colombier "swc3", mipscoload, 103*219b2ee8SDavid du Colombier "instr3C", mipscoxxx, 104*219b2ee8SDavid du Colombier "sd", mipscoload, 105*219b2ee8SDavid du Colombier "sd", mipscoload, 106*219b2ee8SDavid du Colombier "sd", mipscoload, 107*219b2ee8SDavid du Colombier }; 108*219b2ee8SDavid du Colombier 109*219b2ee8SDavid du Colombier static Opcode sopcodes[64] = { 110*219b2ee8SDavid du Colombier "sll", "r%d,r%t,$%a", 111*219b2ee8SDavid du Colombier "special01", mipscoxxx, 112*219b2ee8SDavid du Colombier "srl", "r%d,r%t,$%a", 113*219b2ee8SDavid du Colombier "sra", "r%d,r%t,$%a", 114*219b2ee8SDavid du Colombier "sllv", "r%d,r%t,R%s", 115*219b2ee8SDavid du Colombier "special05", mipscoxxx, 116*219b2ee8SDavid du Colombier "srlv", "r%d,r%t,r%s", 117*219b2ee8SDavid du Colombier "srav", "r%d,r%t,r%s", 118*219b2ee8SDavid du Colombier "jr", "r%s", 119*219b2ee8SDavid du Colombier "jalr", "r%d,r%s", 120*219b2ee8SDavid du Colombier "special0A", mipscoxxx, 121*219b2ee8SDavid du Colombier "special0B", mipscoxxx, 122*219b2ee8SDavid du Colombier "syscall", "", 123*219b2ee8SDavid du Colombier "break", "", 124*219b2ee8SDavid du Colombier "special0E", mipscoxxx, 125*219b2ee8SDavid du Colombier "sync", "", 126*219b2ee8SDavid du Colombier "mfhi", "r%d", 127*219b2ee8SDavid du Colombier "mthi", "r%s", 128*219b2ee8SDavid du Colombier "mflo", "r%d", 129*219b2ee8SDavid du Colombier "mtlo", "r%s", 130*219b2ee8SDavid du Colombier "special14", mipscoxxx, 131*219b2ee8SDavid du Colombier "special15", mipscoxxx, 132*219b2ee8SDavid du Colombier "special16", mipscoxxx, 133*219b2ee8SDavid du Colombier "special17", mipscoxxx, 134*219b2ee8SDavid du Colombier "mult", mipscorsrt, 135*219b2ee8SDavid du Colombier "multu", mipscorsrt, 136*219b2ee8SDavid du Colombier "div", mipscorsrt, 137*219b2ee8SDavid du Colombier "divu", mipscorsrt, 138*219b2ee8SDavid du Colombier "special1C", mipscoxxx, 139*219b2ee8SDavid du Colombier "special1D", mipscoxxx, 140*219b2ee8SDavid du Colombier "special1E", mipscoxxx, 141*219b2ee8SDavid du Colombier "special1F", mipscoxxx, 142*219b2ee8SDavid du Colombier "add", mipscoalu3op, 143*219b2ee8SDavid du Colombier "addu", mipscoalu3op, 144*219b2ee8SDavid du Colombier "sub", mipscoalu3op, 145*219b2ee8SDavid du Colombier "subu", mipscoalu3op, 146*219b2ee8SDavid du Colombier "and", mipscoalu3op, 147*219b2ee8SDavid du Colombier "or", mipscoalu3op, 148*219b2ee8SDavid du Colombier "xor", mipscoalu3op, 149*219b2ee8SDavid du Colombier "nor", mipscoalu3op, 150*219b2ee8SDavid du Colombier "special28", mipscoxxx, 151*219b2ee8SDavid du Colombier "special29", mipscoxxx, 152*219b2ee8SDavid du Colombier "slt", mipscoalu3op, 153*219b2ee8SDavid du Colombier "sltu", mipscoalu3op, 154*219b2ee8SDavid du Colombier "special2C", mipscoxxx, 155*219b2ee8SDavid du Colombier "special2D", mipscoxxx, 156*219b2ee8SDavid du Colombier "special2E", mipscoxxx, 157*219b2ee8SDavid du Colombier "special2F", mipscoxxx, 158*219b2ee8SDavid du Colombier "tge", mipscorsrt, 159*219b2ee8SDavid du Colombier "tgeu", mipscorsrt, 160*219b2ee8SDavid du Colombier "tlt", mipscorsrt, 161*219b2ee8SDavid du Colombier "tltu", mipscorsrt, 162*219b2ee8SDavid du Colombier "teq", mipscorsrt, 163*219b2ee8SDavid du Colombier "special35", mipscoxxx, 164*219b2ee8SDavid du Colombier "tne", mipscorsrt, 165*219b2ee8SDavid du Colombier "special37", mipscoxxx, 166*219b2ee8SDavid du Colombier "special38", mipscoxxx, 167*219b2ee8SDavid du Colombier "special39", mipscoxxx, 168*219b2ee8SDavid du Colombier "special3A", mipscoxxx, 169*219b2ee8SDavid du Colombier "special3B", mipscoxxx, 170*219b2ee8SDavid du Colombier "special3C", mipscoxxx, 171*219b2ee8SDavid du Colombier "special3D", mipscoxxx, 172*219b2ee8SDavid du Colombier "special3E", mipscoxxx, 173*219b2ee8SDavid du Colombier "special3F", mipscoxxx, 174*219b2ee8SDavid du Colombier }; 175*219b2ee8SDavid du Colombier 176*219b2ee8SDavid du Colombier static Opcode ropcodes[32] = { 177*219b2ee8SDavid du Colombier "bltz", mipscoboc0, 178*219b2ee8SDavid du Colombier "bgez", mipscoboc0, 179*219b2ee8SDavid du Colombier "bltzl", mipscoboc0, 180*219b2ee8SDavid du Colombier "bgezl", mipscoboc0, 181*219b2ee8SDavid du Colombier "regimm04", mipscoxxx, 182*219b2ee8SDavid du Colombier "regimm05", mipscoxxx, 183*219b2ee8SDavid du Colombier "regimm06", mipscoxxx, 184*219b2ee8SDavid du Colombier "regimm07", mipscoxxx, 185*219b2ee8SDavid du Colombier "tgei", mipscorsi, 186*219b2ee8SDavid du Colombier "tgeiu", mipscorsi, 187*219b2ee8SDavid du Colombier "tlti", mipscorsi, 188*219b2ee8SDavid du Colombier "tltiu", mipscorsi, 189*219b2ee8SDavid du Colombier "teqi", mipscorsi, 190*219b2ee8SDavid du Colombier "regimm0D", mipscoxxx, 191*219b2ee8SDavid du Colombier "tnei", mipscorsi, 192*219b2ee8SDavid du Colombier "regimm0F", mipscoxxx, 193*219b2ee8SDavid du Colombier "bltzal", mipscoboc0, 194*219b2ee8SDavid du Colombier "bgezal", mipscoboc0, 195*219b2ee8SDavid du Colombier "bltzall", mipscoboc0, 196*219b2ee8SDavid du Colombier "bgezall", mipscoboc0, 197*219b2ee8SDavid du Colombier "regimm14", mipscoxxx, 198*219b2ee8SDavid du Colombier "regimm15", mipscoxxx, 199*219b2ee8SDavid du Colombier "regimm16", mipscoxxx, 200*219b2ee8SDavid du Colombier "regimm17", mipscoxxx, 201*219b2ee8SDavid du Colombier "regimm18", mipscoxxx, 202*219b2ee8SDavid du Colombier "regimm19", mipscoxxx, 203*219b2ee8SDavid du Colombier "regimm1A", mipscoxxx, 204*219b2ee8SDavid du Colombier "regimm1B", mipscoxxx, 205*219b2ee8SDavid du Colombier "regimm1C", mipscoxxx, 206*219b2ee8SDavid du Colombier "regimm1D", mipscoxxx, 207*219b2ee8SDavid du Colombier "regimm1E", mipscoxxx, 208*219b2ee8SDavid du Colombier "regimm1F", mipscoxxx, 209*219b2ee8SDavid du Colombier }; 210*219b2ee8SDavid du Colombier 211*219b2ee8SDavid du Colombier static Opcode fopcodes[64] = { 212*219b2ee8SDavid du Colombier "add.%f", mipscofp3, 213*219b2ee8SDavid du Colombier "sub.%f", mipscofp3, 214*219b2ee8SDavid du Colombier "mul.%f", mipscofp3, 215*219b2ee8SDavid du Colombier "div.%f", mipscofp3, 216*219b2ee8SDavid du Colombier "sqrt.%f", mipscofp2, 217*219b2ee8SDavid du Colombier "abs.%f", mipscofp2, 218*219b2ee8SDavid du Colombier "mov.%f", mipscofp2, 219*219b2ee8SDavid du Colombier "neg.%f", mipscofp2, 220*219b2ee8SDavid du Colombier "finstr08", mipscoxxx, 221*219b2ee8SDavid du Colombier "finstr09", mipscoxxx, 222*219b2ee8SDavid du Colombier "finstr0A", mipscoxxx, 223*219b2ee8SDavid du Colombier "finstr0B", mipscoxxx, 224*219b2ee8SDavid du Colombier "round.w.%f", mipscofp2, 225*219b2ee8SDavid du Colombier "trunc.w%f", mipscofp2, 226*219b2ee8SDavid du Colombier "ceil.w%f", mipscofp2, 227*219b2ee8SDavid du Colombier "floor.w%f", mipscofp2, 228*219b2ee8SDavid du Colombier "finstr10", mipscoxxx, 229*219b2ee8SDavid du Colombier "finstr11", mipscoxxx, 230*219b2ee8SDavid du Colombier "finstr12", mipscoxxx, 231*219b2ee8SDavid du Colombier "finstr13", mipscoxxx, 232*219b2ee8SDavid du Colombier "finstr14", mipscoxxx, 233*219b2ee8SDavid du Colombier "finstr15", mipscoxxx, 234*219b2ee8SDavid du Colombier "finstr16", mipscoxxx, 235*219b2ee8SDavid du Colombier "finstr17", mipscoxxx, 236*219b2ee8SDavid du Colombier "finstr18", mipscoxxx, 237*219b2ee8SDavid du Colombier "finstr19", mipscoxxx, 238*219b2ee8SDavid du Colombier "finstr1A", mipscoxxx, 239*219b2ee8SDavid du Colombier "finstr1B", mipscoxxx, 240*219b2ee8SDavid du Colombier "finstr1C", mipscoxxx, 241*219b2ee8SDavid du Colombier "finstr1D", mipscoxxx, 242*219b2ee8SDavid du Colombier "finstr1E", mipscoxxx, 243*219b2ee8SDavid du Colombier "finstr1F", mipscoxxx, 244*219b2ee8SDavid du Colombier "cvt.s.%f", mipscofp2, 245*219b2ee8SDavid du Colombier "cvt.d.%f", mipscofp2, 246*219b2ee8SDavid du Colombier "cvt.e.%f", mipscofp2, 247*219b2ee8SDavid du Colombier "cvt.q.%f", mipscofp2, 248*219b2ee8SDavid du Colombier "cvt.w.%f", mipscofp2, 249*219b2ee8SDavid du Colombier "finstr25", mipscoxxx, 250*219b2ee8SDavid du Colombier "finstr26", mipscoxxx, 251*219b2ee8SDavid du Colombier "finstr27", mipscoxxx, 252*219b2ee8SDavid du Colombier "finstr28", mipscoxxx, 253*219b2ee8SDavid du Colombier "finstr29", mipscoxxx, 254*219b2ee8SDavid du Colombier "finstr2A", mipscoxxx, 255*219b2ee8SDavid du Colombier "finstr2B", mipscoxxx, 256*219b2ee8SDavid du Colombier "finstr2C", mipscoxxx, 257*219b2ee8SDavid du Colombier "finstr2D", mipscoxxx, 258*219b2ee8SDavid du Colombier "finstr2E", mipscoxxx, 259*219b2ee8SDavid du Colombier "finstr2F", mipscoxxx, 260*219b2ee8SDavid du Colombier "c.f.%f", mipscofpc, 261*219b2ee8SDavid du Colombier "c.un.%f", mipscofpc, 262*219b2ee8SDavid du Colombier "c.eq.%f", mipscofpc, 263*219b2ee8SDavid du Colombier "c.ueq.%f", mipscofpc, 264*219b2ee8SDavid du Colombier "c.olt.%f", mipscofpc, 265*219b2ee8SDavid du Colombier "c.ult.%f", mipscofpc, 266*219b2ee8SDavid du Colombier "c.ole.%f", mipscofpc, 267*219b2ee8SDavid du Colombier "c.ule.%f", mipscofpc, 268*219b2ee8SDavid du Colombier "c.sf.%f", mipscofpc, 269*219b2ee8SDavid du Colombier "c.ngle.%f", mipscofpc, 270*219b2ee8SDavid du Colombier "c.seq.%f", mipscofpc, 271*219b2ee8SDavid du Colombier "c.ngl.%f", mipscofpc, 272*219b2ee8SDavid du Colombier "c.lt.%f", mipscofpc, 273*219b2ee8SDavid du Colombier "c.nge.%f", mipscofpc, 274*219b2ee8SDavid du Colombier "c.le.%f", mipscofpc, 275*219b2ee8SDavid du Colombier "c.ngt.%f", mipscofpc, 276*219b2ee8SDavid du Colombier }; 277*219b2ee8SDavid du Colombier 278*219b2ee8SDavid du Colombier static char fsub[16] = { 279*219b2ee8SDavid du Colombier 's', 'd', 'e', 'q', 'w', '?', '?', '?', 280*219b2ee8SDavid du Colombier '?', '?', '?', '?', '?', '?', '?', '?' 281*219b2ee8SDavid du Colombier }; 282*219b2ee8SDavid du Colombier 283*219b2ee8SDavid du Colombier 284*219b2ee8SDavid du Colombier static int 285*219b2ee8SDavid du Colombier mkinstr(Instr *i, Map *map, ulong pc) 286*219b2ee8SDavid du Colombier { 287*219b2ee8SDavid du Colombier long w; 288*219b2ee8SDavid du Colombier 289*219b2ee8SDavid du Colombier if (get4(map, pc, &w) < 0) { 290*219b2ee8SDavid du Colombier werrstr("can't read instruction: %r"); 291*219b2ee8SDavid du Colombier return -1; 292*219b2ee8SDavid du Colombier } 293*219b2ee8SDavid du Colombier i->addr = pc; 294*219b2ee8SDavid du Colombier i->op = (w >> 26) & 0x3F; 295*219b2ee8SDavid du Colombier i->rs = (w >> 21) & 0x1F; 296*219b2ee8SDavid du Colombier i->rt = (w >> 16) & 0x1F; 297*219b2ee8SDavid du Colombier i->rd = (w >> 11) & 0x1F; 298*219b2ee8SDavid du Colombier i->sa = (w >> 6) & 0x1F; 299*219b2ee8SDavid du Colombier i->function = w & 0x3F; 300*219b2ee8SDavid du Colombier i->immediate = w & 0x0000FFFF; 301*219b2ee8SDavid du Colombier if (i->immediate & 0x8000) 302*219b2ee8SDavid du Colombier i->immediate |= ~0x0000FFFF; 303*219b2ee8SDavid du Colombier i->cofun = w & 0x01FFFFFF; 304*219b2ee8SDavid du Colombier i->target = w & 0x03FFFFFF; 305*219b2ee8SDavid du Colombier i->w0 = w; 306*219b2ee8SDavid du Colombier return 1; 307*219b2ee8SDavid du Colombier } 308*219b2ee8SDavid du Colombier 309*219b2ee8SDavid du Colombier static void 310*219b2ee8SDavid du Colombier bprint(Instr *i, char *fmt, ...) 311*219b2ee8SDavid du Colombier { 312*219b2ee8SDavid du Colombier i->curr = doprint(i->curr, i->end, fmt, (&fmt+1)); 313*219b2ee8SDavid du Colombier } 314*219b2ee8SDavid du Colombier 315*219b2ee8SDavid du Colombier static void 316*219b2ee8SDavid du Colombier format(char *mnemonic, Instr *i, char *f) 317*219b2ee8SDavid du Colombier { 318*219b2ee8SDavid du Colombier if (mnemonic) 319*219b2ee8SDavid du Colombier format(0, i, mnemonic); 320*219b2ee8SDavid du Colombier if (f == 0) 321*219b2ee8SDavid du Colombier return; 322*219b2ee8SDavid du Colombier if (i->curr < i->end) 323*219b2ee8SDavid du Colombier *i->curr++ = '\t'; 324*219b2ee8SDavid du Colombier for ( ; *f && i->curr < i->end; f++) { 325*219b2ee8SDavid du Colombier if (*f != '%') { 326*219b2ee8SDavid du Colombier *i->curr++ = *f; 327*219b2ee8SDavid du Colombier continue; 328*219b2ee8SDavid du Colombier } 329*219b2ee8SDavid du Colombier switch (*++f) { 330*219b2ee8SDavid du Colombier 331*219b2ee8SDavid du Colombier case 's': 332*219b2ee8SDavid du Colombier bprint(i, "%d", i->rs); 333*219b2ee8SDavid du Colombier break; 334*219b2ee8SDavid du Colombier 335*219b2ee8SDavid du Colombier case 't': 336*219b2ee8SDavid du Colombier bprint(i, "%d", i->rt); 337*219b2ee8SDavid du Colombier break; 338*219b2ee8SDavid du Colombier 339*219b2ee8SDavid du Colombier case 'd': 340*219b2ee8SDavid du Colombier bprint(i, "%d", i->rd); 341*219b2ee8SDavid du Colombier break; 342*219b2ee8SDavid du Colombier 343*219b2ee8SDavid du Colombier case 'a': 344*219b2ee8SDavid du Colombier bprint(i, "%d", i->sa); 345*219b2ee8SDavid du Colombier break; 346*219b2ee8SDavid du Colombier 347*219b2ee8SDavid du Colombier case 'l': 348*219b2ee8SDavid du Colombier if (i->rs == 30) { 349*219b2ee8SDavid du Colombier i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY); 350*219b2ee8SDavid du Colombier bprint(i, "(SB)"); 351*219b2ee8SDavid du Colombier } else 352*219b2ee8SDavid du Colombier bprint(i, "%lx(r%d)", i->immediate, i->rs); 353*219b2ee8SDavid du Colombier break; 354*219b2ee8SDavid du Colombier 355*219b2ee8SDavid du Colombier case 'i': 356*219b2ee8SDavid du Colombier bprint(i, "$%lx", i->immediate); 357*219b2ee8SDavid du Colombier break; 358*219b2ee8SDavid du Colombier 359*219b2ee8SDavid du Colombier case 'u': 360*219b2ee8SDavid du Colombier *i->curr++ = '$'; 361*219b2ee8SDavid du Colombier i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY); 362*219b2ee8SDavid du Colombier bprint(i, "(SB)"); 363*219b2ee8SDavid du Colombier break; 364*219b2ee8SDavid du Colombier 365*219b2ee8SDavid du Colombier case 'j': 366*219b2ee8SDavid du Colombier i->curr += symoff(i->curr, i->end-i->curr, 367*219b2ee8SDavid du Colombier (i->target<<2)|(i->addr & 0xF0000000), CANY); 368*219b2ee8SDavid du Colombier bprint(i, "(SB)"); 369*219b2ee8SDavid du Colombier break; 370*219b2ee8SDavid du Colombier 371*219b2ee8SDavid du Colombier case 'b': 372*219b2ee8SDavid du Colombier i->curr += symoff(i->curr, i->end-i->curr, 373*219b2ee8SDavid du Colombier (i->immediate<<2)+i->addr+4, CANY); 374*219b2ee8SDavid du Colombier break; 375*219b2ee8SDavid du Colombier 376*219b2ee8SDavid du Colombier case 'c': 377*219b2ee8SDavid du Colombier bprint(i, "%lux", i->cofun); 378*219b2ee8SDavid du Colombier break; 379*219b2ee8SDavid du Colombier 380*219b2ee8SDavid du Colombier case 'w': 381*219b2ee8SDavid du Colombier bprint(i, "[%lux]", i->w0); 382*219b2ee8SDavid du Colombier break; 383*219b2ee8SDavid du Colombier 384*219b2ee8SDavid du Colombier case 'f': 385*219b2ee8SDavid du Colombier *i->curr++ = fsub[i->rs & 0x0F]; 386*219b2ee8SDavid du Colombier break; 387*219b2ee8SDavid du Colombier 388*219b2ee8SDavid du Colombier case '\0': 389*219b2ee8SDavid du Colombier *i->curr++ = '%'; 390*219b2ee8SDavid du Colombier return; 391*219b2ee8SDavid du Colombier 392*219b2ee8SDavid du Colombier default: 393*219b2ee8SDavid du Colombier bprint(i, "%%%c", *f); 394*219b2ee8SDavid du Colombier break; 395*219b2ee8SDavid du Colombier } 396*219b2ee8SDavid du Colombier } 397*219b2ee8SDavid du Colombier } 398*219b2ee8SDavid du Colombier 399*219b2ee8SDavid du Colombier static void 400*219b2ee8SDavid du Colombier copz(int cop, Instr *i) 401*219b2ee8SDavid du Colombier { 402*219b2ee8SDavid du Colombier char *f, *m, buf[16]; 403*219b2ee8SDavid du Colombier 404*219b2ee8SDavid du Colombier m = buf; 405*219b2ee8SDavid du Colombier f = "%t,%d"; 406*219b2ee8SDavid du Colombier switch (i->rs) { 407*219b2ee8SDavid du Colombier 408*219b2ee8SDavid du Colombier case 0: 409*219b2ee8SDavid du Colombier sprint(buf, "mfc%d", cop); 410*219b2ee8SDavid du Colombier break; 411*219b2ee8SDavid du Colombier 412*219b2ee8SDavid du Colombier case 2: 413*219b2ee8SDavid du Colombier sprint(buf, "cfc%d", cop); 414*219b2ee8SDavid du Colombier break; 415*219b2ee8SDavid du Colombier 416*219b2ee8SDavid du Colombier case 4: 417*219b2ee8SDavid du Colombier sprint(buf, "mtc%d", cop); 418*219b2ee8SDavid du Colombier break; 419*219b2ee8SDavid du Colombier 420*219b2ee8SDavid du Colombier case 6: 421*219b2ee8SDavid du Colombier sprint(buf, "ctc%d", cop); 422*219b2ee8SDavid du Colombier break; 423*219b2ee8SDavid du Colombier 424*219b2ee8SDavid du Colombier case 8: 425*219b2ee8SDavid du Colombier f = "%b"; 426*219b2ee8SDavid du Colombier switch (i->rt) { 427*219b2ee8SDavid du Colombier 428*219b2ee8SDavid du Colombier case 0: 429*219b2ee8SDavid du Colombier sprint(buf, "bc%df", cop); 430*219b2ee8SDavid du Colombier break; 431*219b2ee8SDavid du Colombier 432*219b2ee8SDavid du Colombier case 1: 433*219b2ee8SDavid du Colombier sprint(buf, "bc%dt", cop); 434*219b2ee8SDavid du Colombier break; 435*219b2ee8SDavid du Colombier 436*219b2ee8SDavid du Colombier case 2: 437*219b2ee8SDavid du Colombier sprint(buf, "bc%dfl", cop); 438*219b2ee8SDavid du Colombier break; 439*219b2ee8SDavid du Colombier 440*219b2ee8SDavid du Colombier case 3: 441*219b2ee8SDavid du Colombier sprint(buf, "bc%dtl", cop); 442*219b2ee8SDavid du Colombier break; 443*219b2ee8SDavid du Colombier 444*219b2ee8SDavid du Colombier default: 445*219b2ee8SDavid du Colombier sprint(buf, "cop%d", cop); 446*219b2ee8SDavid du Colombier f = mipscoxxx; 447*219b2ee8SDavid du Colombier break; 448*219b2ee8SDavid du Colombier } 449*219b2ee8SDavid du Colombier break; 450*219b2ee8SDavid du Colombier 451*219b2ee8SDavid du Colombier default: 452*219b2ee8SDavid du Colombier sprint(buf, "cop%d", cop); 453*219b2ee8SDavid du Colombier if (i->rs & 0x10) 454*219b2ee8SDavid du Colombier f = "function %c"; 455*219b2ee8SDavid du Colombier else 456*219b2ee8SDavid du Colombier f = mipscoxxx; 457*219b2ee8SDavid du Colombier break; 458*219b2ee8SDavid du Colombier } 459*219b2ee8SDavid du Colombier format(m, i, f); 460*219b2ee8SDavid du Colombier } 461*219b2ee8SDavid du Colombier 462*219b2ee8SDavid du Colombier static void 463*219b2ee8SDavid du Colombier cop0(Instr *i) 464*219b2ee8SDavid du Colombier { 465*219b2ee8SDavid du Colombier char *m = 0; 466*219b2ee8SDavid du Colombier 467*219b2ee8SDavid du Colombier if (i->rs >= 0x10) { 468*219b2ee8SDavid du Colombier switch (i->cofun) { 469*219b2ee8SDavid du Colombier 470*219b2ee8SDavid du Colombier case 1: 471*219b2ee8SDavid du Colombier m = "tlbr"; 472*219b2ee8SDavid du Colombier break; 473*219b2ee8SDavid du Colombier 474*219b2ee8SDavid du Colombier case 2: 475*219b2ee8SDavid du Colombier m = "tlbwi"; 476*219b2ee8SDavid du Colombier break; 477*219b2ee8SDavid du Colombier 478*219b2ee8SDavid du Colombier case 6: 479*219b2ee8SDavid du Colombier m = "tlbwr"; 480*219b2ee8SDavid du Colombier break; 481*219b2ee8SDavid du Colombier 482*219b2ee8SDavid du Colombier case 8: 483*219b2ee8SDavid du Colombier m = "tlbp"; 484*219b2ee8SDavid du Colombier break; 485*219b2ee8SDavid du Colombier 486*219b2ee8SDavid du Colombier case 16: 487*219b2ee8SDavid du Colombier m = "rfe"; 488*219b2ee8SDavid du Colombier break; 489*219b2ee8SDavid du Colombier 490*219b2ee8SDavid du Colombier case 32: 491*219b2ee8SDavid du Colombier m = "eret"; 492*219b2ee8SDavid du Colombier break; 493*219b2ee8SDavid du Colombier } 494*219b2ee8SDavid du Colombier if (m) { 495*219b2ee8SDavid du Colombier format(m, i, 0); 496*219b2ee8SDavid du Colombier if (i->curr < i->end) 497*219b2ee8SDavid du Colombier *i->curr++ = 0; 498*219b2ee8SDavid du Colombier return; 499*219b2ee8SDavid du Colombier } 500*219b2ee8SDavid du Colombier } 501*219b2ee8SDavid du Colombier copz(0, i); 502*219b2ee8SDavid du Colombier } 503*219b2ee8SDavid du Colombier 504*219b2ee8SDavid du Colombier int 505*219b2ee8SDavid du Colombier _mipscoinst(Map *map, ulong pc, char *buf, int n) 506*219b2ee8SDavid du Colombier { 507*219b2ee8SDavid du Colombier Instr i; 508*219b2ee8SDavid du Colombier Opcode *o; 509*219b2ee8SDavid du Colombier uchar op; 510*219b2ee8SDavid du Colombier 511*219b2ee8SDavid du Colombier i.curr = buf; 512*219b2ee8SDavid du Colombier i.end = buf+n-1; 513*219b2ee8SDavid du Colombier if (mkinstr(&i, map, pc) < 0) 514*219b2ee8SDavid du Colombier return -1; 515*219b2ee8SDavid du Colombier switch (i.op) { 516*219b2ee8SDavid du Colombier 517*219b2ee8SDavid du Colombier case 0x00: /* SPECIAL */ 518*219b2ee8SDavid du Colombier o = sopcodes; 519*219b2ee8SDavid du Colombier op = i.function; 520*219b2ee8SDavid du Colombier break; 521*219b2ee8SDavid du Colombier 522*219b2ee8SDavid du Colombier case 0x01: /* REGIMM */ 523*219b2ee8SDavid du Colombier o = ropcodes; 524*219b2ee8SDavid du Colombier op = i.rt; 525*219b2ee8SDavid du Colombier break; 526*219b2ee8SDavid du Colombier 527*219b2ee8SDavid du Colombier case 0x10: /* COP0 */ 528*219b2ee8SDavid du Colombier cop0(&i); 529*219b2ee8SDavid du Colombier return 4; 530*219b2ee8SDavid du Colombier 531*219b2ee8SDavid du Colombier case 0x11: /* COP1 */ 532*219b2ee8SDavid du Colombier if (i.rs & 0x10) { 533*219b2ee8SDavid du Colombier o = fopcodes; 534*219b2ee8SDavid du Colombier op = i.function; 535*219b2ee8SDavid du Colombier break; 536*219b2ee8SDavid du Colombier } 537*219b2ee8SDavid du Colombier /*FALLTHROUGH*/ 538*219b2ee8SDavid du Colombier case 0x12: /* COP2 */ 539*219b2ee8SDavid du Colombier case 0x13: /* COP3 */ 540*219b2ee8SDavid du Colombier copz(i.op-0x10, &i); 541*219b2ee8SDavid du Colombier return 4; 542*219b2ee8SDavid du Colombier 543*219b2ee8SDavid du Colombier default: 544*219b2ee8SDavid du Colombier o = opcodes; 545*219b2ee8SDavid du Colombier op = i.op; 546*219b2ee8SDavid du Colombier break; 547*219b2ee8SDavid du Colombier } 548*219b2ee8SDavid du Colombier format(o[op].mnemonic, &i, o[op].mipsco); 549*219b2ee8SDavid du Colombier return 4; 550*219b2ee8SDavid du Colombier } 551