|
|
1.1 ! root 1: #include <u.h> ! 2: #include <libc.h> ! 3: #include <bio.h> ! 4: #include <mach.h> ! 5: /* ! 6: * Mips-specific debugger interface ! 7: */ ! 8: ! 9: static char *mipsexcep(Map*, Rgetter); ! 10: static int mipsfoll(Map*, ulong, Rgetter, ulong*); ! 11: static int mipsinst(Map*, ulong, char, char*, int); ! 12: static int mipsdas(Map*, ulong, char*, int); ! 13: static int mipsinstlen(Map*, ulong); ! 14: /* ! 15: * Debugger interface ! 16: */ ! 17: Machdata mipsmach = ! 18: { ! 19: {0, 0, 0, 0xD}, /* break point */ ! 20: 4, /* break point size */ ! 21: ! 22: beswab, /* short to local byte order */ ! 23: beswal, /* long to local byte order */ ! 24: risctrace, /* C traceback */ ! 25: riscframe, /* Frame finder */ ! 26: 0, /* ublock fixup */ ! 27: mipsexcep, /* print exception */ ! 28: 0, /* breakpoint fixup */ ! 29: beieeesftos, /* single precision float printer */ ! 30: beieeedftos, /* double precisioin float printer */ ! 31: mipsfoll, /* following addresses */ ! 32: mipsinst, /* print instruction */ ! 33: mipsdas, /* dissembler */ ! 34: mipsinstlen, /* instruction size */ ! 35: }; ! 36: ! 37: static char *excname[] = ! 38: { ! 39: "external interrupt", ! 40: "TLB modification", ! 41: "TLB miss (load or fetch)", ! 42: "TLB miss (store)", ! 43: "address error (load or fetch)", ! 44: "address error (store)", ! 45: "bus error (fetch)", ! 46: "bus error (data load or store)", ! 47: "system call", ! 48: "breakpoint", ! 49: "reserved instruction", ! 50: "coprocessor unusable", ! 51: "arithmetic overflow", ! 52: "undefined 13", ! 53: "undefined 14", ! 54: "system call", ! 55: /* the following is made up */ ! 56: "floating point exception" /* FPEXC */ ! 57: }; ! 58: ! 59: static char* ! 60: mipsexcep(Map *map, Rgetter rget) ! 61: { ! 62: int e; ! 63: long c; ! 64: ! 65: c = (*rget)(map, "CAUSE"); ! 66: if(c & 0x00002000) /* INTR3 */ ! 67: e = 16; /* Floating point exception */ ! 68: else ! 69: e = (c>>2)&0x0F; ! 70: return excname[e]; ! 71: } ! 72: ! 73: /* mips disassembler and related functions */ ! 74: ! 75: static char FRAMENAME[] = ".frame"; ! 76: ! 77: typedef struct { ! 78: ulong addr; ! 79: uchar op; /* bits 31-26 */ ! 80: uchar rs; /* bits 25-21 */ ! 81: uchar rt; /* bits 20-16 */ ! 82: uchar rd; /* bits 15-11 */ ! 83: uchar sa; /* bits 10-6 */ ! 84: uchar function; /* bits 5-0 */ ! 85: long immediate; /* bits 15-0 */ ! 86: ulong cofun; /* bits 24-0 */ ! 87: ulong target; /* bits 25-0 */ ! 88: long w0; ! 89: long w1; ! 90: int size; /* instruction size */ ! 91: char *curr; /* fill point in buffer */ ! 92: char *end; /* end of buffer */ ! 93: char *err; /* error message */ ! 94: } Instr; ! 95: ! 96: static Map *mymap; ! 97: ! 98: static int ! 99: decode (ulong pc, Instr *i) ! 100: { ! 101: long w; ! 102: ! 103: if (get4(mymap, pc, &w) < 0) { ! 104: werrstr("can't read instruction: %r"); ! 105: return -1; ! 106: } ! 107: i->addr = pc; ! 108: i->size = 1; ! 109: i->op = (w >> 26) & 0x3F; ! 110: i->rs = (w >> 21) & 0x1F; ! 111: i->rt = (w >> 16) & 0x1F; ! 112: i->rd = (w >> 11) & 0x1F; ! 113: i->sa = (w >> 6) & 0x1F; ! 114: i->function = w & 0x3F; ! 115: i->immediate = w & 0x0000FFFF; ! 116: if (i->immediate & 0x8000) ! 117: i->immediate |= ~0x0000FFFF; ! 118: i->cofun = w & 0x01FFFFFF; ! 119: i->target = w & 0x03FFFFFF; ! 120: i->w0 = w; ! 121: return 1; ! 122: } ! 123: ! 124: static int ! 125: mkinstr(ulong pc, Instr *i) ! 126: { ! 127: Instr x; ! 128: ! 129: if (decode(pc, i) < 0) ! 130: return -1; ! 131: /* ! 132: * if it's a LUI followed by an ORI, ! 133: * it's an immediate load of a large constant. ! 134: * fix the LUI immediate in any case. ! 135: */ ! 136: if (i->op == 0x0F) { ! 137: if (decode(pc+4, &x) < 0) ! 138: return 0; ! 139: i->immediate <<= 16; ! 140: if (x.op == 0x0D && x.rs == x.rt && x.rt == i->rt) { ! 141: i->immediate |= (x.immediate & 0xFFFF); ! 142: i->w1 = x.w0; ! 143: i->size++; ! 144: return 1; ! 145: } ! 146: } ! 147: /* ! 148: * if it's a LWC1 followed by another LWC1 ! 149: * into an adjacent register, it's a load of ! 150: * a floating point double. ! 151: */ ! 152: else if (i->op == 0x31 && (i->rt & 0x01)) { ! 153: if (decode(pc+4, &x) < 0) ! 154: return 0; ! 155: if (x.op == 0x31 && x.rt == (i->rt - 1) && x.rs == i->rs) { ! 156: i->rt -= 1; ! 157: i->w1 = x.w0; ! 158: i->size++; ! 159: return 1; ! 160: } ! 161: } ! 162: /* ! 163: * similarly for double stores ! 164: */ ! 165: else if (i->op == 0x39 && (i->rt & 0x01)) { ! 166: if (decode(pc+4, &x) < 0) ! 167: return 0; ! 168: if (x.op == 0x39 && x.rt == (i->rt - 1) && x.rs == i->rs) { ! 169: i->rt -= 1; ! 170: i->w1 = x.w0; ! 171: i->size++; ! 172: } ! 173: } ! 174: return 1; ! 175: } ! 176: ! 177: static void ! 178: bprint(Instr *i, char *fmt, ...) ! 179: { ! 180: i->curr = doprint(i->curr, i->end, fmt, (&fmt+1)); ! 181: } ! 182: ! 183: typedef struct Opcode Opcode; ! 184: ! 185: struct Opcode { ! 186: char *mnemonic; ! 187: void (*f)(Opcode *, Instr *); ! 188: char *ken; ! 189: }; ! 190: ! 191: static void format(char *, Instr *, char *); ! 192: ! 193: static void ! 194: branch(Opcode *o, Instr *i) ! 195: { ! 196: if (i->rs == 0 && i->rt == 0) ! 197: format("JMP", i, "%b"); ! 198: else if (i->rs == 0) ! 199: format(o->mnemonic, i, "R%t,%b"); ! 200: else if (i->rt < 2) ! 201: format(o->mnemonic, i, "R%s,%b"); ! 202: else ! 203: format(o->mnemonic, i, "R%s,R%t,%b"); ! 204: } ! 205: ! 206: static void ! 207: addi(Opcode *o, Instr *i) ! 208: { ! 209: if (i->rs == i->rt) ! 210: format(o->mnemonic, i, "%i,R%t"); ! 211: else if (i->rs == 0) ! 212: format("MOVW", i, "%i,R%t"); ! 213: else if (i->rs == 30) { ! 214: bprint(i, "MOVW\t$"); ! 215: i->curr += symoff(i->curr, i->end-i->curr, ! 216: i->immediate+mach->sb, CANY); ! 217: bprint(i, "(SB),R%d", i->rt); ! 218: } ! 219: else ! 220: format(o->mnemonic, i, o->ken); ! 221: } ! 222: ! 223: static void ! 224: andi(Opcode *o, Instr *i) ! 225: { ! 226: if (i->rs == i->rt) ! 227: format(o->mnemonic, i, "%i,R%t"); ! 228: else ! 229: format(o->mnemonic, i, o->ken); ! 230: } ! 231: ! 232: static int ! 233: plocal(Instr *i, char *m, char r, int store) ! 234: { ! 235: int offset; ! 236: char *reg; ! 237: Symbol s; ! 238: ! 239: if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) ! 240: return 0; ! 241: if (s.value > i->immediate) { ! 242: if(!getauto(&s, s.value-i->immediate, CAUTO, &s)) ! 243: return 0; ! 244: reg = "(SP)"; ! 245: offset = i->immediate; ! 246: } else { ! 247: offset = i->immediate-s.value; ! 248: if (!getauto(&s, offset-4, CPARAM, &s)) ! 249: return 0; ! 250: reg = "(FP)"; ! 251: } ! 252: if (store) ! 253: bprint(i, "%s\t%c%d,%s+%d%s", m, r, i->rt, s.name, offset, reg); ! 254: else ! 255: bprint(i, "%s\t%s+%d%s,%c%d", m, s.name, offset, reg, r, i->rt); ! 256: return 1; ! 257: } ! 258: ! 259: static void ! 260: lw(Opcode *o, Instr *i, char r) ! 261: { ! 262: char *m; ! 263: ! 264: if (r == 'F') { ! 265: if (i->size == 2) ! 266: m = "MOVD"; ! 267: else ! 268: m = "MOVF"; ! 269: } ! 270: else ! 271: m = o->mnemonic; ! 272: if (i->rs == 29 && plocal(i, m, r, 0)) ! 273: return; ! 274: ! 275: if (i->rs == 30 && mach->sb) { ! 276: bprint(i, "%s\t", m); ! 277: i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY); ! 278: bprint(i, "(SB),%c%d", r, i->rt); ! 279: return; ! 280: } ! 281: if (r == 'F') ! 282: format(m, i, "%l,F%t"); ! 283: else ! 284: format(m, i, o->ken); ! 285: } ! 286: ! 287: static void ! 288: load(Opcode *o, Instr *i) ! 289: { ! 290: lw(o, i, 'R'); ! 291: } ! 292: ! 293: static void ! 294: lwc1(Opcode *o, Instr *i) ! 295: { ! 296: lw(o, i, 'F'); ! 297: } ! 298: ! 299: static void ! 300: sw(Opcode *o, Instr *i, char r) ! 301: { ! 302: char *m; ! 303: ! 304: if (r == 'F') { ! 305: if (i->size == 2) ! 306: m = "MOVD"; ! 307: else ! 308: m = "MOVF"; ! 309: } ! 310: else ! 311: m = o->mnemonic; ! 312: if (i->rs == 29 && plocal(i, m, r, 1)) ! 313: return; ! 314: ! 315: if (i->rs == 30 && mach->sb) { ! 316: bprint(i, "%s\t%c%d,", m, r, i->rt); ! 317: i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY); ! 318: bprint(i, "(SB)"); ! 319: return; ! 320: } ! 321: if (r == 'F') ! 322: format(m, i, "F%t,%l"); ! 323: else ! 324: format(m, i, o->ken); ! 325: } ! 326: ! 327: static void ! 328: store(Opcode *o, Instr *i) ! 329: { ! 330: sw(o, i, 'R'); ! 331: } ! 332: ! 333: static void ! 334: swc1(Opcode *o, Instr *i) ! 335: { ! 336: sw(o, i, 'F'); ! 337: } ! 338: ! 339: static void ! 340: sll(Opcode *o, Instr *i) ! 341: { ! 342: if (i->w0 == 0) ! 343: bprint(i, "NOOP"); ! 344: else if (i->rd == i->rt) ! 345: format(o->mnemonic, i, "$%a,R%d"); ! 346: else ! 347: format(o->mnemonic, i, o->ken); ! 348: } ! 349: ! 350: static void ! 351: sl32(Opcode *o, Instr *i) ! 352: { ! 353: i->sa += 32; ! 354: if (i->rd == i->rt) ! 355: format(o->mnemonic, i, "$%a,R%d"); ! 356: else ! 357: format(o->mnemonic, i, o->ken); ! 358: } ! 359: ! 360: static void ! 361: sllv(Opcode *o, Instr *i) ! 362: { ! 363: if (i->rd == i->rt) ! 364: format(o->mnemonic, i, "R%s,R%d"); ! 365: else ! 366: format(o->mnemonic, i, o->ken); ! 367: } ! 368: ! 369: static void ! 370: jal(Opcode *o, Instr *i) ! 371: { ! 372: if (i->rd == 31) ! 373: format("JAL", i, "(R%s)"); ! 374: else ! 375: format(o->mnemonic, i, o->ken); ! 376: } ! 377: ! 378: static void ! 379: add(Opcode *o, Instr *i) ! 380: { ! 381: if (i->rd == i->rs) ! 382: format(o->mnemonic, i, "R%t,R%d"); ! 383: else if (i->rd == i->rt) ! 384: format(o->mnemonic, i, "R%s,R%d"); ! 385: else ! 386: format(o->mnemonic, i, o->ken); ! 387: } ! 388: ! 389: static void ! 390: sub(Opcode *o, Instr *i) ! 391: { ! 392: if (i->rd == i->rs) ! 393: format(o->mnemonic, i, "R%t,R%d"); ! 394: else ! 395: format(o->mnemonic, i, o->ken); ! 396: } ! 397: ! 398: static void ! 399: or(Opcode *o, Instr *i) ! 400: { ! 401: if (i->rs == 0 && i->rt == 0) ! 402: format("MOVW", i, "$0,R%d"); ! 403: else if (i->rs == 0) ! 404: format("MOVW", i, "R%t,R%d"); ! 405: else if (i->rt == 0) ! 406: format("MOVW", i, "R%s,R%d"); ! 407: else ! 408: add(o, i); ! 409: } ! 410: ! 411: static void ! 412: nor(Opcode *o, Instr *i) ! 413: { ! 414: if (i->rs == 0 && i->rt == 0 && i->rd == 0) ! 415: format("NOP", i, 0); ! 416: else ! 417: add(o, i); ! 418: } ! 419: ! 420: static char mipscoload[] = "r%t,%l"; ! 421: static char mipsload[] = "%l,R%t"; ! 422: static char mipsstore[] = "R%t,%l"; ! 423: static char mipsalui[] = "%i,R%s,R%t"; ! 424: static char mipsalu3op[] = "R%t,R%s,R%d"; ! 425: static char mipsrtrs[] = "R%t,R%s"; ! 426: static char mipscorsrt[] = "r%s,r%t"; ! 427: static char mipscorsi[] = "r%s,%i"; ! 428: static char mipscoxxx[] = "%w"; ! 429: static char mipscofp3[] = "f%a,f%d,f%t"; /* fd,fs,ft */ ! 430: static char mipsfp3[] = "F%t,F%d,F%a"; ! 431: static char mipscofp2[] = "f%a,f%d"; /* fd,fs */ ! 432: static char mipsfp2[] = "F%d,F%a"; ! 433: static char mipscofpc[] = "f%d,f%t"; /* fs,ft */ ! 434: static char mipsfpc[] = "F%t,F%d"; ! 435: ! 436: static Opcode opcodes[64] = { ! 437: 0, 0, 0, ! 438: 0, 0, 0, ! 439: "JMP", 0, "%j", ! 440: "JAL", 0, "%j", ! 441: "BEQ", branch, 0, ! 442: "BNE", branch, 0, ! 443: "BLEZ", branch, 0, ! 444: "BGTZ", branch, 0, ! 445: "ADD", addi, mipsalui, ! 446: "ADDU", addi, mipsalui, ! 447: "SGT", 0, mipsalui, ! 448: "SGTU", 0, mipsalui, ! 449: "AND", andi, mipsalui, ! 450: "OR", andi, mipsalui, ! 451: "XOR", andi, mipsalui, ! 452: "MOVW", 0, "$%u,R%t", ! 453: "cop0", 0, 0, ! 454: "cop1", 0, 0, ! 455: "cop2", 0, 0, ! 456: "cop3", 0, 0, ! 457: "BEQL", branch, 0, ! 458: "BNEL", branch, 0, ! 459: "BLEZL", branch, 0, ! 460: "BGTZL", branch, 0, ! 461: "instr18", 0, mipscoxxx, ! 462: "instr19", 0, mipscoxxx, ! 463: "MOVVL", load, mipsload, ! 464: "MOVVR", load, mipsload, ! 465: "instr1C", 0, mipscoxxx, ! 466: "instr1D", 0, mipscoxxx, ! 467: "instr1E", 0, mipscoxxx, ! 468: "instr1F", 0, mipscoxxx, ! 469: "MOVB", load, mipsload, ! 470: "MOVH", load, mipsload, ! 471: "lwl", 0, mipscoload, ! 472: "MOVW", load, mipsload, ! 473: "MOVBU", load, mipsload, ! 474: "MOVHU", load, mipsload, ! 475: "lwr", 0, mipscoload, ! 476: "instr27", 0, mipscoxxx, ! 477: "MOVB", store, mipsstore, ! 478: "MOVH", store, mipsstore, ! 479: "swl", 0, mipscoload, ! 480: "MOVW", store, mipsstore, ! 481: "MOVVL", store, mipsstore, ! 482: "MOVVR", store, mipsstore, ! 483: "swr", 0, mipscoload, ! 484: "CACHE", 0, "%C,%l", ! 485: "ll", 0, mipscoload, ! 486: "MOVW", lwc1, mipscoload, ! 487: "lwc2", 0, mipscoload, ! 488: "lwc3", 0, mipscoload, ! 489: "instr34", 0, mipscoxxx, ! 490: "ldc1", 0, mipscoload, ! 491: "ldc2", 0, mipscoload, ! 492: "MOVV", load, mipsload, ! 493: "sc", 0, mipscoload, ! 494: "swc1", swc1, mipscoload, ! 495: "swc2", 0, mipscoload, ! 496: "swc3", 0, mipscoload, ! 497: "instr3C", 0, mipscoxxx, ! 498: "sdc1", 0, mipscoload, ! 499: "sdc2", 0, mipscoload, ! 500: "MOVV", store, mipsstore, ! 501: }; ! 502: ! 503: static Opcode sopcodes[64] = { ! 504: "SLL", sll, "$%a,R%t,R%d", ! 505: "special01", 0, mipscoxxx, ! 506: "SRL", sll, "$%a,R%t,R%d", ! 507: "SRA", sll, "$%a,R%t,R%d", ! 508: "SLL", sllv, "R%s,R%t,R%d", ! 509: "special05", 0, mipscoxxx, ! 510: "SRL", sllv, "R%s,R%t,R%d", ! 511: "SRA", sllv, "R%s,R%t,R%d", ! 512: "JMP", 0, "(R%s)", ! 513: "jal", jal, "r%d,r%s", ! 514: "special0A", 0, mipscoxxx, ! 515: "special0B", 0, mipscoxxx, ! 516: "SYSCALL", 0, 0, ! 517: "BREAK", 0, 0, ! 518: "special0E", 0, mipscoxxx, ! 519: "SYNC", 0, 0, ! 520: "MOVW", 0, "HI,R%d", ! 521: "MOVW", 0, "R%s,HI", ! 522: "MOVW", 0, "LO,R%d", ! 523: "MOVW", 0, "R%s,LO", ! 524: "SLLV", sllv, "R%s,R%t,R%d", ! 525: "special15", 0, mipscoxxx, ! 526: "SRLV", sllv, "R%s,R%t,R%d", ! 527: "SRAV", sllv, "R%s,R%t,R%d", ! 528: "MUL", 0, mipsrtrs, ! 529: "MULU", 0, mipsrtrs, ! 530: "DIV", 0, mipsrtrs, ! 531: "DIVU", 0, mipsrtrs, ! 532: "special1C", 0, mipscoxxx, ! 533: "special1D", 0, mipscoxxx, ! 534: "special1E", 0, mipscoxxx, ! 535: "special1F", 0, mipscoxxx, ! 536: "ADD", add, mipsalu3op, ! 537: "ADDU", add, mipsalu3op, ! 538: "SUB", sub, mipsalu3op, ! 539: "SUBU", sub, mipsalu3op, ! 540: "AND", add, mipsalu3op, ! 541: "OR", or, mipsalu3op, ! 542: "XOR", add, mipsalu3op, ! 543: "NOR", nor, mipsalu3op, ! 544: "special28", 0, mipscoxxx, ! 545: "special29", 0, mipscoxxx, ! 546: "SGT", 0, mipsalu3op, ! 547: "SGTU", 0, mipsalu3op, ! 548: "special2C", 0, mipscoxxx, ! 549: "special2D", 0, mipscoxxx, ! 550: "special2E", 0, mipscoxxx, ! 551: "special2F", 0, mipscoxxx, ! 552: "tge", 0, mipscorsrt, ! 553: "tgeu", 0, mipscorsrt, ! 554: "tlt", 0, mipscorsrt, ! 555: "tltu", 0, mipscorsrt, ! 556: "teq", 0, mipscorsrt, ! 557: "special35", 0, mipscoxxx, ! 558: "tne", 0, mipscorsrt, ! 559: "special37", 0, mipscoxxx, ! 560: "SLLV", sll, "$%a,R%t,R%d", ! 561: "special39", 0, mipscoxxx, ! 562: "SRLV", sll, "$%a,R%t,R%d", ! 563: "SRAV", sll, "$%a,R%t,R%d", ! 564: "SLLV", sl32, "$%a,R%t,R%d", ! 565: "special3D", 0, mipscoxxx, ! 566: "SRLV", sl32, "$%a,R%t,R%d", ! 567: "SRAV", sl32, "$%a,R%t,R%d", ! 568: }; ! 569: ! 570: static Opcode ropcodes[32] = { ! 571: "BLTZ", branch, 0, ! 572: "BGEZ", branch, 0, ! 573: "BLTZL", branch, 0, ! 574: "BGEZL", branch, 0, ! 575: "regimm04", 0, mipscoxxx, ! 576: "regimm05", 0, mipscoxxx, ! 577: "regimm06", 0, mipscoxxx, ! 578: "regimm07", 0, mipscoxxx, ! 579: "tgei", 0, mipscorsi, ! 580: "tgeiu", 0, mipscorsi, ! 581: "tlti", 0, mipscorsi, ! 582: "tltiu", 0, mipscorsi, ! 583: "teqi", 0, mipscorsi, ! 584: "regimm0D", 0, mipscoxxx, ! 585: "tnei", 0, mipscorsi, ! 586: "regimm0F", 0, mipscoxxx, ! 587: "BLTZAL", branch, 0, ! 588: "BGEZAL", branch, 0, ! 589: "BLTZALL", branch, 0, ! 590: "BGEZALL", branch, 0, ! 591: "regimm14", 0, mipscoxxx, ! 592: "regimm15", 0, mipscoxxx, ! 593: "regimm16", 0, mipscoxxx, ! 594: "regimm17", 0, mipscoxxx, ! 595: "regimm18", 0, mipscoxxx, ! 596: "regimm19", 0, mipscoxxx, ! 597: "regimm1A", 0, mipscoxxx, ! 598: "regimm1B", 0, mipscoxxx, ! 599: "regimm1C", 0, mipscoxxx, ! 600: "regimm1D", 0, mipscoxxx, ! 601: "regimm1E", 0, mipscoxxx, ! 602: "regimm1F", 0, mipscoxxx, ! 603: }; ! 604: ! 605: static Opcode fopcodes[64] = { ! 606: "ADD%f", 0, mipsfp3, ! 607: "SUB%f", 0, mipsfp3, ! 608: "MUL%f", 0, mipsfp3, ! 609: "DIV%f", 0, mipsfp3, ! 610: "sqrt.%f", 0, mipscofp2, ! 611: "ABS%f", 0, mipsfp2, ! 612: "MOV%f", 0, mipsfp2, ! 613: "NEG%f", 0, mipsfp2, ! 614: "finstr08", 0, mipscoxxx, ! 615: "finstr09", 0, mipscoxxx, ! 616: "finstr0A", 0, mipscoxxx, ! 617: "finstr0B", 0, mipscoxxx, ! 618: "round.w.%f", 0, mipscofp2, ! 619: "trunc.w%f", 0, mipscofp2, ! 620: "ceil.w%f", 0, mipscofp2, ! 621: "floor.w%f", 0, mipscofp2, ! 622: "finstr10", 0, mipscoxxx, ! 623: "finstr11", 0, mipscoxxx, ! 624: "finstr12", 0, mipscoxxx, ! 625: "finstr13", 0, mipscoxxx, ! 626: "finstr14", 0, mipscoxxx, ! 627: "finstr15", 0, mipscoxxx, ! 628: "finstr16", 0, mipscoxxx, ! 629: "finstr17", 0, mipscoxxx, ! 630: "finstr18", 0, mipscoxxx, ! 631: "finstr19", 0, mipscoxxx, ! 632: "finstr1A", 0, mipscoxxx, ! 633: "finstr1B", 0, mipscoxxx, ! 634: "finstr1C", 0, mipscoxxx, ! 635: "finstr1D", 0, mipscoxxx, ! 636: "finstr1E", 0, mipscoxxx, ! 637: "finstr1F", 0, mipscoxxx, ! 638: "cvt.s.%f", 0, mipscofp2, ! 639: "cvt.d.%f", 0, mipscofp2, ! 640: "cvt.e.%f", 0, mipscofp2, ! 641: "cvt.q.%f", 0, mipscofp2, ! 642: "cvt.w.%f", 0, mipscofp2, ! 643: "finstr25", 0, mipscoxxx, ! 644: "finstr26", 0, mipscoxxx, ! 645: "finstr27", 0, mipscoxxx, ! 646: "finstr28", 0, mipscoxxx, ! 647: "finstr29", 0, mipscoxxx, ! 648: "finstr2A", 0, mipscoxxx, ! 649: "finstr2B", 0, mipscoxxx, ! 650: "finstr2C", 0, mipscoxxx, ! 651: "finstr2D", 0, mipscoxxx, ! 652: "finstr2E", 0, mipscoxxx, ! 653: "finstr2F", 0, mipscoxxx, ! 654: "c.f.%f", 0, mipscofpc, ! 655: "c.un.%f", 0, mipscofpc, ! 656: "CMPEQ%f", 0, mipsfpc, ! 657: "c.ueq.%f", 0, mipscofpc, ! 658: "c.olt.%f", 0, mipscofpc, ! 659: "c.ult.%f", 0, mipscofpc, ! 660: "c.ole.%f", 0, mipscofpc, ! 661: "c.ule.%f", 0, mipscofpc, ! 662: "c.sf.%f", 0, mipscofpc, ! 663: "c.ngle.%f", 0, mipscofpc, ! 664: "c.seq.%f", 0, mipscofpc, ! 665: "c.ngl.%f", 0, mipscofpc, ! 666: "CMPGT%f", 0, mipsfpc, ! 667: "c.nge.%f", 0, mipscofpc, ! 668: "CMPGE%f", 0, mipsfpc, ! 669: "c.ngt.%f", 0, mipscofpc, ! 670: }; ! 671: ! 672: static char *cop0regs[32] = { ! 673: "INDEX", "RANDOM", "TLBPHYS", "EntryLo0", ! 674: "CONTEXT", "PageMask", "Wired", "Error", ! 675: "BADVADDR", "Count", "TLBVIRT", "Compare", ! 676: "STATUS", "CAUSE", "EPC", "PRID", ! 677: "Config", "LLadr", "WatchLo", "WatchHi", ! 678: "20", "21", "22", "23", ! 679: "24", "25", "26", "CacheErr", ! 680: "TagLo", "TagHi", "ErrorEPC", "31" ! 681: }; ! 682: ! 683: static char fsub[16] = { ! 684: 'F', 'D', 'e', 'q', 'W', '?', '?', '?', ! 685: '?', '?', '?', '?', '?', '?', '?', '?' ! 686: }; ! 687: ! 688: static char *cacheps[] = { ! 689: "I", "D", "SI", "SD" ! 690: }; ! 691: ! 692: static char *cacheop[] = { ! 693: "IWBI", "ILT", "IST", "CDE", "HI", "HWBI", "HWB", "HSV" ! 694: }; ! 695: ! 696: static void ! 697: format(char *mnemonic, Instr *i, char *f) ! 698: { ! 699: if (mnemonic) ! 700: format(0, i, mnemonic); ! 701: if (f == 0) ! 702: return; ! 703: if (mnemonic) ! 704: if (i->curr < i->end) ! 705: *i->curr++ = '\t'; ! 706: for ( ; *f && i->curr < i->end; f++) { ! 707: if (*f != '%') { ! 708: *i->curr++ = *f; ! 709: continue; ! 710: } ! 711: switch (*++f) { ! 712: ! 713: case 's': ! 714: bprint(i, "%d", i->rs); ! 715: break; ! 716: ! 717: case 't': ! 718: bprint(i, "%d", i->rt); ! 719: break; ! 720: ! 721: case 'd': ! 722: bprint(i, "%d", i->rd); ! 723: break; ! 724: ! 725: case 'a': ! 726: bprint(i, "%d", i->sa); ! 727: break; ! 728: ! 729: case 'l': ! 730: bprint(i, "%lx(R%d)",i->immediate, i->rs); ! 731: break; ! 732: ! 733: case 'i': ! 734: bprint(i, "$%lx", i->immediate); ! 735: break; ! 736: ! 737: case 'u': ! 738: i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY); ! 739: bprint(i, "(SB)"); ! 740: break; ! 741: ! 742: case 'j': ! 743: i->curr += symoff(i->curr, i->end-i->curr, ! 744: (i->target<<2)|(i->addr & 0xF0000000), CANY); ! 745: bprint(i, "(SB)"); ! 746: break; ! 747: ! 748: case 'b': ! 749: i->curr += symoff(i->curr, i->end-i->curr, ! 750: (i->immediate<<2)+i->addr+4, CANY); ! 751: break; ! 752: ! 753: case 'c': ! 754: bprint(i, "$%lx", i->cofun); ! 755: break; ! 756: ! 757: case 'w': ! 758: bprint(i, "[%lux]", i->w0); ! 759: break; ! 760: ! 761: case 'm': ! 762: bprint(i, "M(%s)", cop0regs[i->rd]); ! 763: break; ! 764: ! 765: case 'f': ! 766: *i->curr++ = fsub[i->rs & 0x0F]; ! 767: break; ! 768: ! 769: case 'C': ! 770: bprint(i, "%s%s", cacheps[i->rt & 3], cacheop[(i->rt>>2) & 7]); ! 771: break; ! 772: ! 773: case '\0': ! 774: *i->curr++ = '%'; ! 775: return; ! 776: ! 777: default: ! 778: bprint(i, "%%%c", *f); ! 779: break; ! 780: } ! 781: } ! 782: *i->curr = 0; ! 783: } ! 784: ! 785: static void ! 786: copz(int cop, Instr *i) ! 787: { ! 788: char *f, *m, buf[16]; ! 789: ! 790: m = buf; ! 791: f = "%t,%d"; ! 792: switch (i->rs) { ! 793: ! 794: case 0: ! 795: sprint(buf, "mfc%d", cop); ! 796: break; ! 797: ! 798: case 2: ! 799: sprint(buf, "cfc%d", cop); ! 800: break; ! 801: ! 802: case 4: ! 803: sprint(buf, "mtc%d", cop); ! 804: break; ! 805: ! 806: case 6: ! 807: sprint(buf, "ctc%d", cop); ! 808: break; ! 809: ! 810: case 8: ! 811: f = "%b"; ! 812: switch (i->rt) { ! 813: ! 814: case 0: ! 815: sprint(buf, "bc%df", cop); ! 816: break; ! 817: ! 818: case 1: ! 819: sprint(buf, "bc%dt", cop); ! 820: break; ! 821: ! 822: case 2: ! 823: sprint(buf, "bc%dfl", cop); ! 824: break; ! 825: ! 826: case 3: ! 827: sprint(buf, "bc%dtl", cop); ! 828: break; ! 829: ! 830: default: ! 831: sprint(buf, "cop%d", cop); ! 832: f = mipscoxxx; ! 833: break; ! 834: } ! 835: break; ! 836: ! 837: default: ! 838: sprint(buf, "cop%d", cop); ! 839: if (i->rs & 0x10) ! 840: f = "function %c"; ! 841: else ! 842: f = mipscoxxx; ! 843: break; ! 844: } ! 845: format(m, i, f); ! 846: } ! 847: ! 848: static void ! 849: cop0(Instr *i) ! 850: { ! 851: char *m = 0; ! 852: ! 853: if (i->rs < 8) { ! 854: switch (i->rs) { ! 855: ! 856: case 0: ! 857: case 1: ! 858: format("MOVW", i, "%m,R%t"); ! 859: return; ! 860: ! 861: case 4: ! 862: case 5: ! 863: format("MOVW", i, "R%t,%m"); ! 864: return; ! 865: } ! 866: } ! 867: else if (i->rs >= 0x10) { ! 868: switch (i->cofun) { ! 869: ! 870: case 1: ! 871: m = "TLBR"; ! 872: break; ! 873: ! 874: case 2: ! 875: m = "TLBWI"; ! 876: break; ! 877: ! 878: case 6: ! 879: m = "TLBWR"; ! 880: break; ! 881: ! 882: case 8: ! 883: m = "TLBP"; ! 884: break; ! 885: ! 886: case 16: ! 887: m = "RFE"; ! 888: break; ! 889: ! 890: case 32: ! 891: m = "ERET"; ! 892: break; ! 893: } ! 894: if (m) { ! 895: format(m, i, 0); ! 896: return; ! 897: } ! 898: } ! 899: copz(0, i); ! 900: } ! 901: ! 902: static void ! 903: cop1(Instr *i) ! 904: { ! 905: char *m = "MOVW"; ! 906: ! 907: switch (i->rs) { ! 908: ! 909: case 0: ! 910: format(m, i, "F%d,R%t"); ! 911: return; ! 912: ! 913: case 2: ! 914: format(m, i, "FCR%d,R%t"); ! 915: return; ! 916: ! 917: case 4: ! 918: format(m, i, "R%t,F%d"); ! 919: return; ! 920: ! 921: case 6: ! 922: format(m, i, "R%t,FCR%d"); ! 923: return; ! 924: ! 925: case 8: ! 926: switch (i->rt) { ! 927: ! 928: case 0: ! 929: format("BFPF", i, "%b"); ! 930: return; ! 931: ! 932: case 1: ! 933: format("BFPT", i, "%b"); ! 934: return; ! 935: } ! 936: break; ! 937: } ! 938: copz(1, i); ! 939: } ! 940: ! 941: static int ! 942: printins(Map *map, ulong pc, char *buf, int n) ! 943: { ! 944: Instr i; ! 945: Opcode *o; ! 946: uchar op; ! 947: ! 948: i.curr = buf; ! 949: i.end = buf+n-1; ! 950: mymap = map; ! 951: if (mkinstr(pc, &i) < 0) ! 952: return -1; ! 953: switch (i.op) { ! 954: ! 955: case 0x00: /* SPECIAL */ ! 956: o = sopcodes; ! 957: op = i.function; ! 958: break; ! 959: ! 960: case 0x01: /* REGIMM */ ! 961: o = ropcodes; ! 962: op = i.rt; ! 963: break; ! 964: ! 965: case 0x10: /* COP0 */ ! 966: cop0(&i); ! 967: return i.size*4; ! 968: ! 969: case 0x11: /* COP1 */ ! 970: if (i.rs & 0x10) { ! 971: o = fopcodes; ! 972: op = i.function; ! 973: break; ! 974: } ! 975: cop1(&i); ! 976: return i.size*4; ! 977: ! 978: case 0x12: /* COP2 */ ! 979: case 0x13: /* COP3 */ ! 980: copz(i.op-0x10, &i); ! 981: return i.size*4; ! 982: ! 983: default: ! 984: o = opcodes; ! 985: op = i.op; ! 986: break; ! 987: } ! 988: if (o[op].f) ! 989: (*o[op].f)(&o[op], &i); ! 990: else ! 991: format(o[op].mnemonic, &i, o[op].ken); ! 992: return i.size*4; ! 993: } ! 994: ! 995: extern int _mipscoinst(Map *, ulong, char*, int); ! 996: ! 997: /* modifier 'I' toggles the default disassembler type */ ! 998: static int ! 999: mipsinst(Map *map, ulong pc, char modifier, char *buf, int n) ! 1000: { ! 1001: if ((asstype == AMIPSCO && modifier == 'i') ! 1002: || (asstype == AMIPS && modifier == 'I')) ! 1003: return _mipscoinst(map, pc, buf, n); ! 1004: else ! 1005: return printins(map, pc, buf, n); ! 1006: } ! 1007: ! 1008: static int ! 1009: mipsdas(Map *map, ulong pc, char *buf, int n) ! 1010: { ! 1011: Instr i; ! 1012: ! 1013: i.curr = buf; ! 1014: i.end = buf+n; ! 1015: mymap = map; ! 1016: if (mkinstr(pc, &i) < 0) ! 1017: return -1; ! 1018: if (i.end-i.curr > 8) ! 1019: i.curr = _hexify(buf, i.w0, 7); ! 1020: if (i.size == 2 && i.end-i.curr > 9) { ! 1021: *i.curr++ = ' '; ! 1022: i.curr = _hexify(i.curr, i.w1, 7); ! 1023: } ! 1024: *i.curr = 0; ! 1025: return i.size*4; ! 1026: } ! 1027: ! 1028: static int ! 1029: mipsinstlen(Map *map, ulong pc) ! 1030: { ! 1031: Instr i; ! 1032: ! 1033: mymap = map; ! 1034: if (mkinstr(pc, &i) < 0) ! 1035: return -1; ! 1036: return i.size*4; ! 1037: } ! 1038: ! 1039: static int ! 1040: mipsfoll(Map *map, ulong pc, Rgetter rget, ulong *foll) ! 1041: { ! 1042: ulong w, l; ! 1043: char buf[8]; ! 1044: Instr i; ! 1045: ! 1046: mymap = map; ! 1047: if (mkinstr(pc, &i) < 0) ! 1048: return -1; ! 1049: w = i.w0; ! 1050: if((w&0xF3600000) == 0x41000000){ /* branch on coprocessor */ ! 1051: Conditional: ! 1052: foll[0] = pc+8; ! 1053: l = ((w&0xFFFF)<<2); ! 1054: if(w & 0x8000) ! 1055: l |= 0xFFFC0000; ! 1056: foll[1] = pc+4 + l; ! 1057: return 2; ! 1058: } ! 1059: ! 1060: l = (w&0xFC000000)>>26; ! 1061: switch(l){ ! 1062: case 0: /* SPECIAL */ ! 1063: if((w&0x3E) == 0x08){ /* JR, JALR */ ! 1064: sprint(buf, "R%d", (w>>21)&0x1F); ! 1065: foll[0] = (*rget)(map, buf); ! 1066: return 1; ! 1067: } ! 1068: foll[0] = pc+i.size*4; ! 1069: return 1; ! 1070: case 0x30: /* Load-Linked followed by NOP, STC */ ! 1071: foll[0] = pc+12; ! 1072: return 1; ! 1073: case 1: /* BCOND */ ! 1074: case 4: /* BEQ */ ! 1075: case 5: /* BNE */ ! 1076: case 6: /* BLEZ */ ! 1077: case 7: /* BGTZ */ ! 1078: goto Conditional; ! 1079: case 2: /* J */ ! 1080: case 3: /* JAL */ ! 1081: foll[0] = (pc&0xF0000000) | ((w&0x03FFFFFF)<<2); ! 1082: return 1; ! 1083: } ! 1084: ! 1085: foll[0] = pc+i.size*4; ! 1086: return 1; ! 1087: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.