|
|
1.1 ! root 1: #include <u.h> ! 2: #include <libc.h> ! 3: #include <bio.h> ! 4: #include <mach.h> ! 5: ! 6: /* ! 7: * Sparc-specific debugger interface ! 8: */ ! 9: ! 10: static char *sparcexcep(Map*, Rgetter); ! 11: static int sparcfoll(Map*, ulong, Rgetter, ulong*); ! 12: static int sparcinst(Map*, ulong, char, char*, int); ! 13: static int sparcdas(Map*, ulong, char*, int); ! 14: static int sparcinstlen(Map*, ulong); ! 15: ! 16: Machdata sparcmach = ! 17: { ! 18: {0x91, 0xd0, 0x20, 0x01}, /* breakpoint: TA $1 */ ! 19: 4, /* break point size */ ! 20: ! 21: beswab, /* convert short to local byte order */ ! 22: beswal, /* convert long to local byte order */ ! 23: risctrace, /* C traceback */ ! 24: riscframe, /* frame finder */ ! 25: 0, /* ublock fixup */ ! 26: sparcexcep, /* print exception */ ! 27: 0, /* breakpoint fixup */ ! 28: beieeesftos, /* single precision float printer */ ! 29: beieeedftos, /* double precision float printer */ ! 30: sparcfoll, /* following addresses */ ! 31: sparcinst, /* print instruction */ ! 32: sparcdas, /* dissembler */ ! 33: sparcinstlen, /* instruction size */ ! 34: }; ! 35: ! 36: static char *trapname[] = ! 37: { ! 38: "reset", ! 39: "instruction access exception", ! 40: "illegal instruction", ! 41: "privileged instruction", ! 42: "fp disabled", ! 43: "window overflow", ! 44: "window underflow", ! 45: "unaligned address", ! 46: "fp exception", ! 47: "data access exception", ! 48: "tag overflow", ! 49: }; ! 50: ! 51: static char* ! 52: excname(ulong tbr) ! 53: { ! 54: static char buf[32]; ! 55: ! 56: if(tbr < sizeof trapname/sizeof(char*)) ! 57: return trapname[tbr]; ! 58: if(tbr >= 130) ! 59: sprint(buf, "trap instruction %d", tbr-128); ! 60: else if(17<=tbr && tbr<=31) ! 61: sprint(buf, "interrupt level %d", tbr-16); ! 62: else switch(tbr){ ! 63: case 36: ! 64: return "cp disabled"; ! 65: case 40: ! 66: return "cp exception"; ! 67: case 128: ! 68: return "syscall"; ! 69: case 129: ! 70: return "breakpoint"; ! 71: default: ! 72: sprint(buf, "unknown trap %d", tbr); ! 73: } ! 74: Return: ! 75: return buf; ! 76: } ! 77: ! 78: static char* ! 79: sparcexcep(Map *map, Rgetter rget) ! 80: { ! 81: long tbr; ! 82: ! 83: tbr = (*rget)(map, "TBR"); ! 84: tbr = (tbr&0xFFF)>>4; ! 85: return excname(tbr); ! 86: } ! 87: ! 88: /* Sparc disassembler and related functions */ ! 89: ! 90: struct opcode { ! 91: char *mnemonic; ! 92: void (*f)(struct instr*, char*); ! 93: int flag; ! 94: }; ! 95: ! 96: static char FRAMENAME[] = ".frame"; ! 97: ! 98: typedef struct instr Instr; ! 99: ! 100: struct instr { ! 101: uchar op; /* bits 31-30 */ ! 102: uchar rd; /* bits 29-25 */ ! 103: uchar op2; /* bits 24-22 */ ! 104: uchar a; /* bit 29 */ ! 105: uchar cond; /* bits 28-25 */ ! 106: uchar op3; /* bits 24-19 */ ! 107: uchar rs1; /* bits 18-14 */ ! 108: uchar i; /* bit 13 */ ! 109: uchar asi; /* bits 12-05 */ ! 110: uchar rs2; /* bits 04-00 */ ! 111: short simm13; /* bits 12-00, signed */ ! 112: ushort opf; /* bits 13-05 */ ! 113: ulong immdisp22; /* bits 21-00 */ ! 114: ulong simmdisp22; /* bits 21-00, signed */ ! 115: ulong disp30; /* bits 30-00 */ ! 116: ulong imm32; /* SETHI+ADD constant */ ! 117: int target; /* SETHI+ADD dest reg */ ! 118: long w0; ! 119: long w1; ! 120: ulong addr; /* pc of instruction */ ! 121: char *curr; /* current fill level in output buffer */ ! 122: char *end; /* end of buffer */ ! 123: int size; /* number of longs in instr */ ! 124: char *err; /* errmsg */ ! 125: }; ! 126: ! 127: static Map *mymap; /* disassembler context */ ! 128: static int dascase; ! 129: ! 130: static int mkinstr(ulong, Instr*); ! 131: static void bra1(Instr*, char*, char*[]); ! 132: static void bra(Instr*, char*); ! 133: static void fbra(Instr*, char*); ! 134: static void cbra(Instr*, char*); ! 135: static void unimp(Instr*, char*); ! 136: static void fpop(Instr*, char*); ! 137: static void shift(Instr*, char*); ! 138: static void sethi(Instr*, char*); ! 139: static void load(Instr*, char*); ! 140: static void loada(Instr*, char*); ! 141: static void store(Instr*, char*); ! 142: static void storea(Instr*, char*); ! 143: static void add(Instr*, char*); ! 144: static void cmp(Instr*, char*); ! 145: static void wr(Instr*, char*); ! 146: static void jmpl(Instr*, char*); ! 147: static void rd(Instr*, char*); ! 148: static void loadf(Instr*, char*); ! 149: static void storef(Instr*, char*); ! 150: static void loadc(Instr*, char*); ! 151: static void loadcsr(Instr*, char*); ! 152: static void trap(Instr*, char*); ! 153: ! 154: static struct opcode sparcop0[8] = { ! 155: [0] "UNIMP", unimp, 0, /* page 137 */ ! 156: [2] "B", bra, 0, /* page 119 */ ! 157: [4] "SETHI", sethi, 0, /* page 104 */ ! 158: [6] "FB", fbra, 0, /* page 121 */ ! 159: [7] "CB", cbra, 0, /* page 123 */ ! 160: }; ! 161: ! 162: static struct opcode sparcop2[64] = { ! 163: [0x00] "ADD", add, 0, /* page 108 */ ! 164: [0x10] "ADDCC", add, 0, ! 165: [0x08] "ADDX", add, 0, ! 166: [0x18] "ADDXCC", add, 0, ! 167: ! 168: [0x20] "TADD", add, 0, /* page 109 */ ! 169: [0x22] "TADDCCTV", add, 0, ! 170: ! 171: [0x04] "SUB", add, 0, /* page 110 */ ! 172: [0x14] "SUBCC", cmp, 0, ! 173: [0x0C] "SUBX", add, 0, ! 174: [0x1C] "SUBXCC", add, 0, ! 175: ! 176: [0x21] "TSUB", add, 0, /* page 111 */ ! 177: [0x23] "TSUBCCTV", add, 0, ! 178: ! 179: [0x24] "MULSCC", add, 0, /* page 112 */ ! 180: ! 181: [0x0A] "UMUL", add, 0, /* page 113 */ ! 182: [0x0B] "SMUL", add, 0, ! 183: [0x1A] "UMULCC", add, 0, ! 184: [0x1B] "SMULCC", add, 0, ! 185: ! 186: [0x0E] "UDIV", add, 0, /* page 115 */ ! 187: [0x0F] "SDIV", add, 0, ! 188: [0x1E] "UDIVCC", add, 0, ! 189: [0x1F] "SDIVCC", add, 0, ! 190: ! 191: [0x01] "AND", add, 0, /* page 106 */ ! 192: [0x11] "ANDCC", add, 0, ! 193: [0x05] "ANDN", add, 0, ! 194: [0x15] "ANDNCC", add, 0, ! 195: [0x02] "OR", add, 0, ! 196: [0x12] "ORCC", add, 0, ! 197: [0x06] "ORN", add, 0, ! 198: [0x16] "ORNCC", add, 0, ! 199: [0x03] "XOR", add, 0, ! 200: [0x13] "XORCC", add, 0, ! 201: [0x07] "XORN", add, 0, ! 202: [0x17] "XORNCC", add, 0, ! 203: ! 204: [0x25] "SLL", shift, 0, /* page 107 */ ! 205: [0x26] "SRL", shift, 0, ! 206: [0x27] "SRA", shift, 0, ! 207: ! 208: [0x3C] "SAVE", add, 0, /* page 117 */ ! 209: [0x3D] "RESTORE", add, 0, ! 210: ! 211: [0x38] "JMPL", jmpl, 0, /* page 126 */ ! 212: ! 213: [0x39] "RETT", add, 0, /* page 127 */ ! 214: ! 215: [0x3A] "T", trap, 0, /* page 129 */ ! 216: ! 217: [0x28] "rdy", rd, 0, /* page 131 */ ! 218: [0x29] "rdpsr", rd, 0, ! 219: [0x2A] "rdwim", rd, 0, ! 220: [0x2B] "rdtbr", rd, 0, ! 221: ! 222: [0x30] "wry", wr, 0, /* page 133 */ ! 223: [0x31] "wrpsr", wr, 0, ! 224: [0x32] "wrwim", wr, 0, ! 225: [0x33] "wrtbr", wr, 0, ! 226: ! 227: [0x3B] "flush", add, 0, /* page 138 */ ! 228: ! 229: [0x34] "FPOP", fpop, 0, /* page 140 */ ! 230: [0x35] "FPOP", fpop, 0, ! 231: }; ! 232: ! 233: static struct opcode sparcop3[64]={ ! 234: [0x09] "ldsb", load, 0, /* page 90 */ ! 235: [0x19] "ldsba", loada, 0, ! 236: [0x0A] "ldsh", load, 0, ! 237: [0x1A] "ldsha", loada, 0, ! 238: [0x01] "ldub", load, 0, ! 239: [0x11] "lduba", loada, 0, ! 240: [0x02] "lduh", load, 0, ! 241: [0x12] "lduha", loada, 0, ! 242: [0x00] "ld", load, 0, ! 243: [0x10] "lda", loada, 0, ! 244: [0x03] "ldd", load, 0, ! 245: [0x13] "ldda", loada, 0, ! 246: ! 247: [0x20] "ldf", loadf, 0, /* page 92 */ ! 248: [0x23] "lddf", loadf, 0, ! 249: [0x21] "ldfsr", loadf,0, ! 250: ! 251: [0x30] "ldc", loadc, 0, /* page 94 */ ! 252: [0x33] "lddc", loadc, 0, ! 253: [0x31] "ldcsr", loadcsr,0, ! 254: ! 255: [0x05] "stb", store, 0, /* page 95 */ ! 256: [0x15] "stba", storea, 0, ! 257: [0x06] "sth", store, 0, ! 258: [0x16] "stha", storea, 0, ! 259: [0x04] "st", store, 0, ! 260: [0x14] "sta", storea, 0, ! 261: [0x07] "std", store, 0, ! 262: [0x17] "stda", storea, 0, ! 263: ! 264: [0x24] "stf", storef, 0, /* page 97 */ ! 265: [0x27] "stdf", storef, 0, ! 266: [0x25] "stfsr", storef,0, ! 267: [0x26] "stdfq", storef,0, ! 268: ! 269: [0x34] "stc", loadc, 0, /* page 99 */ ! 270: [0x37] "stdc", loadc, 0, ! 271: [0x35] "stcsr", loadcsr,0, ! 272: [0x36] "stdcq", loadcsr,0, ! 273: ! 274: [0x0D] "ldstub", store, 0, /* page 101 */ ! 275: [0x1D] "ldstuba", storea, 0, ! 276: ! 277: [0x0F] "swap", load, 0, /* page 102 */ ! 278: [0x1F] "swapa", loada, 0, ! 279: }; ! 280: ! 281: static void ! 282: bprint(Instr *i, char *fmt, ...) ! 283: { ! 284: i->curr = doprint(i->curr, i->end, fmt, (&fmt+1)); ! 285: } ! 286: ! 287: static int ! 288: decode(ulong pc, Instr *i) ! 289: { ! 290: long w; ! 291: ! 292: if (get4(mymap, pc, &w) < 0) { ! 293: werrstr("can't read instruction: %r"); ! 294: return -1; ! 295: } ! 296: i->op = (w >> 30) & 0x03; ! 297: i->rd = (w >> 25) & 0x1F; ! 298: i->op2 = (w >> 22) & 0x07; ! 299: i->a = (w >> 29) & 0x01; ! 300: i->cond = (w >> 25) & 0x0F; ! 301: i->op3 = (w >> 19) & 0x3F; ! 302: i->rs1 = (w >> 14) & 0x1F; ! 303: i->i = (w >> 13) & 0x01; ! 304: i->asi = (w >> 5) & 0xFF; ! 305: i->rs2 = (w >> 0) & 0x1F; ! 306: i->simm13 = (w >> 0) & 0x1FFF; ! 307: if(i->simm13 & (1<<12)) ! 308: i->simm13 |= ~((1<<13)-1); ! 309: i->opf = (w >> 5) & 0x1FF; ! 310: i->immdisp22 = (w >> 0) & 0x3FFFFF; ! 311: i->simmdisp22 = i->immdisp22; ! 312: if(i->simmdisp22 & (1<<21)) ! 313: i->simmdisp22 |= ~((1<<22)-1); ! 314: i->disp30 = (w >> 0) & 0x3FFFFFFF; ! 315: i->w0 = w; ! 316: i->target = -1; ! 317: i->addr = pc; ! 318: i->size = 1; ! 319: return 1; ! 320: } ! 321: ! 322: static int ! 323: mkinstr(ulong pc, Instr *i) ! 324: { ! 325: Instr xi; ! 326: ! 327: if (decode(pc, i) < 0) ! 328: return -1; ! 329: if(i->op==0 && i->op2==4 && !dascase){ /* SETHI */ ! 330: if (decode(pc+4, &xi) < 0) ! 331: return -1; ! 332: if(xi.op==2 && xi.op3==0) /* ADD */ ! 333: if(xi.i == 1 && xi.rs1 == i->rd){ /* immediate to same reg */ ! 334: i->imm32 = xi.simm13 + (i->immdisp22<<10); ! 335: i->target = xi.rd; ! 336: i->w1 = xi.w0; ! 337: i->size++; ! 338: return 1; ! 339: } ! 340: } ! 341: if(i->op==2 && i->opf==1 && !dascase){ /* FMOVS */ ! 342: if (decode(pc+4, &xi) < 0) ! 343: return -1; ! 344: if(i->op==2 && i->opf==1) /* FMOVS */ ! 345: if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){ /* next pair */ ! 346: i->w1 = xi.w0; ! 347: i->size++; ! 348: } ! 349: } ! 350: return 1; ! 351: } ! 352: ! 353: static int ! 354: printins(Map *map, ulong pc, char *buf, int n) ! 355: { ! 356: Instr instr; ! 357: void (*f)(Instr*, char*); ! 358: ! 359: mymap = map; ! 360: memset(&instr, 0, sizeof(instr)); ! 361: instr.curr = buf; ! 362: instr.end = buf+n-1; ! 363: if (mkinstr(pc, &instr) < 0) ! 364: return -1; ! 365: switch(instr.op){ ! 366: case 0: ! 367: f = sparcop0[instr.op2].f; ! 368: if(f) ! 369: (*f)(&instr, sparcop0[instr.op2].mnemonic); ! 370: else ! 371: bprint(&instr, "unknown %lux", instr.w0); ! 372: break; ! 373: ! 374: case 1: ! 375: bprint(&instr, "%X", "CALL\t"); ! 376: instr.curr += symoff(instr.curr, instr.end-instr.curr, ! 377: pc+instr.disp30*4, CTEXT); ! 378: if (!dascase) ! 379: bprint(&instr, "(SB)"); ! 380: break; ! 381: ! 382: case 2: ! 383: f = sparcop2[instr.op3].f; ! 384: if(f) ! 385: (*f)(&instr, sparcop2[instr.op3].mnemonic); ! 386: else ! 387: bprint(&instr, "unknown %lux", instr.w0); ! 388: break; ! 389: ! 390: case 3: ! 391: f = sparcop3[instr.op3].f; ! 392: if(f) ! 393: (*f)(&instr, sparcop3[instr.op3].mnemonic); ! 394: else ! 395: bprint(&instr, "unknown %lux", instr.w0); ! 396: break; ! 397: } ! 398: if (instr.err) { ! 399: if (instr.curr != buf) ! 400: bprint(&instr, "\t\t;"); ! 401: bprint(&instr, instr.err); ! 402: } ! 403: return instr.size*4; ! 404: } ! 405: ! 406: /* convert to lower case from upper, according to dascase */ ! 407: static int ! 408: Xconv(void *oa, Fconv *f) ! 409: { ! 410: char buf[128]; ! 411: char *s, *t; ! 412: ! 413: if(dascase){ ! 414: for(s=*(char**)oa,t=buf; *t = *s; s++,t++) ! 415: if('A'<=*t && *t<='Z') ! 416: *t += 'a'-'A'; ! 417: strconv(buf, f); ! 418: }else ! 419: strconv(*(char**)oa, f); ! 420: return sizeof(char*); ! 421: } ! 422: ! 423: static int ! 424: sparcinst(Map *map, ulong pc, char modifier, char *buf, int n) ! 425: { ! 426: static int fmtinstalled = 0; ! 427: ! 428: /* a modifier of 'I' toggles the dissassembler type */ ! 429: if (!fmtinstalled) { ! 430: fmtinstalled = 1; ! 431: fmtinstall('X', Xconv); ! 432: } ! 433: if ((asstype == ASUNSPARC && modifier == 'i') ! 434: || (asstype == ASPARC && modifier == 'I')) ! 435: dascase = 'a'-'A'; ! 436: else ! 437: dascase = 0; ! 438: return printins(map, pc, buf, n); ! 439: } ! 440: ! 441: static int ! 442: sparcdas(Map *map, ulong pc, char *buf, int n) ! 443: { ! 444: Instr instr; ! 445: ! 446: mymap = map; ! 447: memset(&instr, 0, sizeof(instr)); ! 448: instr.curr = buf; ! 449: instr.end = buf+n-1; ! 450: if (mkinstr(pc, &instr) < 0) ! 451: return -1; ! 452: if (instr.end-instr.curr > 8) ! 453: instr.curr = _hexify(instr.curr, instr.w0, 7); ! 454: if (instr.end-instr.curr > 9 && instr.size == 2) { ! 455: *instr.curr++ = ' '; ! 456: instr.curr = _hexify(instr.curr, instr.w1, 7); ! 457: } ! 458: *instr.curr = 0; ! 459: return instr.size*4; ! 460: } ! 461: ! 462: static int ! 463: sparcinstlen(Map *map, ulong pc) ! 464: { ! 465: Instr i; ! 466: ! 467: mymap = map; ! 468: if (mkinstr(pc, &i) < 0) ! 469: return -1; ! 470: return i.size*4; ! 471: } ! 472: ! 473: static int ! 474: plocal(Instr *i) ! 475: { ! 476: int offset; ! 477: Symbol s; ! 478: ! 479: if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) ! 480: return -1; ! 481: if (s.value > i->simm13) { ! 482: if(getauto(&s, s.value-i->simm13, CAUTO, &s)) { ! 483: bprint(i, "%s+%d(SP)", s.name, s.value); ! 484: return 1; ! 485: } ! 486: } else { ! 487: offset = i->simm13-s.value; ! 488: if (getauto(&s, offset-4, CPARAM, &s)) { ! 489: bprint(i, "%s+%d(FP)", s.name, offset); ! 490: return 1; ! 491: } ! 492: } ! 493: return -1; ! 494: } ! 495: ! 496: static void ! 497: address(Instr *i) ! 498: { ! 499: Symbol s, s2; ! 500: long off, off1; ! 501: ! 502: if (i->rs1 == 1 && plocal(i) >= 0) ! 503: return; ! 504: off = mach->sb+i->simm13; ! 505: if(i->rs1 == 2 && findsym(off, CANY, &s) ! 506: && s.value-off < 4096 ! 507: && (s.class == CDATA || s.class == CTEXT)) { ! 508: if(off==s.value && s.name[0]=='$'){ ! 509: off1 = 0; ! 510: get4(mymap, s.value, &off1); ! 511: if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){ ! 512: bprint(i, "$%s(SB)", s2.name); ! 513: return; ! 514: } ! 515: } ! 516: bprint(i, "%s", s.name); ! 517: if (s.value != off) ! 518: bprint(i, "+%lux", s.value-off); ! 519: bprint(i, "(SB)"); ! 520: return; ! 521: } ! 522: bprint(i, "%lux(R%d)", i->simm13, i->rs1); ! 523: } ! 524: ! 525: static void ! 526: unimp(Instr *i, char *m) ! 527: { ! 528: bprint(i, "%X", m); ! 529: } ! 530: ! 531: static char *bratab[16] = { /* page 91 */ ! 532: [0X8] "A", ! 533: [0X0] "N", ! 534: [0X9] "NE", ! 535: [0X1] "E", ! 536: [0XA] "G", ! 537: [0X2] "LE", ! 538: [0XB] "GE", ! 539: [0X3] "L", ! 540: [0XC] "GU", ! 541: [0X4] "LEU", ! 542: [0XD] "CC", ! 543: [0X5] "CS", ! 544: [0XE] "POS", ! 545: [0X6] "NEG", ! 546: [0XF] "VC", ! 547: [0X7] "VS", ! 548: }; ! 549: ! 550: static char *fbratab[16] = { /* page 91 */ ! 551: [0X8] "A", ! 552: [0X0] "N", ! 553: [0X7] "U", ! 554: [0X6] "G", ! 555: [0X5] "UG", ! 556: [0X4] "L", ! 557: [0X3] "UL", ! 558: [0X2] "LG", ! 559: [0X1] "NE", ! 560: [0X9] "E", ! 561: [0XA] "UE", ! 562: [0XB] "GE", ! 563: [0XC] "UGE", ! 564: [0XD] "LE", ! 565: [0XE] "ULE", ! 566: [0XF] "O", ! 567: }; ! 568: ! 569: static char *cbratab[16] = { /* page 91 */ ! 570: [0X8] "A", ! 571: [0X0] "N", ! 572: [0X7] "3", ! 573: [0X6] "2", ! 574: [0X5] "23", ! 575: [0X4] "1", ! 576: [0X3] "13", ! 577: [0X2] "12", ! 578: [0X1] "123", ! 579: [0X9] "0", ! 580: [0XA] "03", ! 581: [0XB] "02", ! 582: [0XC] "023", ! 583: [0XD] "01", ! 584: [0XE] "013", ! 585: [0XF] "012", ! 586: }; ! 587: ! 588: static void ! 589: bra1(Instr *i, char *m, char *tab[]) ! 590: { ! 591: long imm; ! 592: ! 593: imm = i->simmdisp22; ! 594: if(i->a) ! 595: bprint(i, "%X%X.%c\t", m, tab[i->cond], 'A'+dascase); ! 596: else ! 597: bprint(i, "%X%X\t", m, tab[i->cond]); ! 598: i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT); ! 599: if (!dascase) ! 600: bprint(i, "(SB)"); ! 601: } ! 602: ! 603: static void ! 604: bra(Instr *i, char *m) /* page 91 */ ! 605: { ! 606: bra1(i, m, bratab); ! 607: } ! 608: ! 609: static void ! 610: fbra(Instr *i, char *m) /* page 93 */ ! 611: { ! 612: bra1(i, m, fbratab); ! 613: } ! 614: ! 615: static void ! 616: cbra(Instr *i, char *m) /* page 95 */ ! 617: { ! 618: bra1(i, m, cbratab); ! 619: } ! 620: ! 621: static void ! 622: trap(Instr *i, char *m) /* page 101 */ ! 623: { ! 624: if(i->i == 0) ! 625: bprint(i, "%X%X\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1); ! 626: else ! 627: bprint(i, "%X%X\t$%lux+R%d", m, bratab[i->cond], i->simm13, i->rs1); ! 628: } ! 629: ! 630: static void ! 631: sethi(Instr *i, char *m) /* page 89 */ ! 632: { ! 633: ulong imm; ! 634: ! 635: imm = i->immdisp22<<10; ! 636: if(dascase){ ! 637: bprint(i, "%X\t%lux, R%d", m, imm, i->rd); ! 638: return; ! 639: } ! 640: if(imm==0 && i->rd==0){ ! 641: bprint(i, "NOP"); ! 642: return; ! 643: } ! 644: if(i->target < 0){ ! 645: bprint(i, "MOVW\t$%lux, R%d", imm, i->rd); ! 646: return; ! 647: } ! 648: bprint(i, "MOVW\t$%lux, R%d", i->imm32, i->target); ! 649: } ! 650: ! 651: static char ldtab[] = { ! 652: 'W', ! 653: 'B', ! 654: 'H', ! 655: 'D', ! 656: }; ! 657: ! 658: static char* ! 659: moveinstr(int op3, char *m) ! 660: { ! 661: char *s; ! 662: int c; ! 663: static char buf[8]; ! 664: ! 665: if(!dascase){ ! 666: /* batshit cases */ ! 667: if(op3 == 0xF || op3 == 0x1F) ! 668: return "SWAP"; ! 669: if(op3 == 0xD || op3 == 0x1D) ! 670: return "TAS"; /* really LDSTUB */ ! 671: c = ldtab[op3&3]; ! 672: s = ""; ! 673: if((op3&11)==1 || (op3&11)==2) ! 674: s="U"; ! 675: sprint(buf, "MOV%c%s", c, s); ! 676: return buf; ! 677: } ! 678: return m; ! 679: } ! 680: ! 681: static void ! 682: load(Instr *i, char *m) /* page 68 */ ! 683: { ! 684: m = moveinstr(i->op3, m); ! 685: if(i->i == 0) ! 686: bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd); ! 687: else{ ! 688: bprint(i, "%s\t", m); ! 689: address(i); ! 690: bprint(i, ", R%d", i->rd); ! 691: } ! 692: } ! 693: ! 694: static void ! 695: loada(Instr *i, char *m) /* page 68 */ ! 696: { ! 697: m = moveinstr(i->op3, m); ! 698: if(i->i == 0) ! 699: bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd); ! 700: else ! 701: bprint(i, "unknown ld asi %lux", i->w0); ! 702: } ! 703: ! 704: static void ! 705: store(Instr *i, char *m) /* page 74 */ ! 706: { ! 707: m = moveinstr(i->op3, m); ! 708: if(i->i == 0) ! 709: bprint(i, "%s\tR%d, (R%d+R%d)", ! 710: m, i->rd, i->rs1, i->rs2); ! 711: else{ ! 712: bprint(i, "%s\tR%d, ", m, i->rd); ! 713: address(i); ! 714: } ! 715: } ! 716: ! 717: static void ! 718: storea(Instr *i, char *m) /* page 74 */ ! 719: { ! 720: m = moveinstr(i->op3, m); ! 721: if(i->i == 0) ! 722: bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi); ! 723: else ! 724: bprint(i, "%s\tR%d, %d(R%d, %d), ???", m, i->rd, i->simm13, i->rs1, i->asi); ! 725: } ! 726: ! 727: void ! 728: shift(Instr *i, char *m) /* page 88 */ ! 729: { ! 730: if(i->i == 0){ ! 731: if(i->rs1 == i->rd) ! 732: if(dascase) ! 733: bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2); ! 734: else ! 735: bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1); ! 736: else ! 737: if(dascase) ! 738: bprint(i, "%X\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd); ! 739: else ! 740: bprint(i, "%X\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd); ! 741: }else{ ! 742: if(i->rs1 == i->rd) ! 743: if(dascase) ! 744: bprint(i, "%X\t$%d,R%d", m, i->simm13&0x1F, i->rs1); ! 745: else ! 746: bprint(i, "%X\tR%d, $%d", m, i->rs1, i->simm13&0x1F); ! 747: else ! 748: if(dascase) ! 749: bprint(i, "%X\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd); ! 750: else ! 751: bprint(i, "%X\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd); ! 752: } ! 753: } ! 754: ! 755: static void ! 756: add(Instr *i, char *m) /* page 82 */ ! 757: { ! 758: if(i->i == 0){ ! 759: if(dascase) ! 760: bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2); ! 761: else ! 762: if(i->op3==2 && i->rs1==0 && i->rd) /* OR R2, R0, R1 */ ! 763: bprint(i, "MOVW\tR%d", i->rs2); ! 764: else ! 765: bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1); ! 766: }else{ ! 767: if(dascase) ! 768: bprint(i, "%X\tR%d, $%lux", m, i->rs1, i->simm13); ! 769: else ! 770: if(i->op3==0 && i->rd && i->rs1==0) /* ADD $x, R0, R1 */ ! 771: bprint(i, "MOVW\t$%lux", i->simm13); ! 772: else if(i->op3==0 && i->rd && i->rs1==2){ ! 773: /* ADD $x, R2, R1 -> MOVW $x(SB), R1 */ ! 774: bprint(i, "MOVW\t$"); ! 775: address(i); ! 776: } else ! 777: bprint(i, "%X\t$%lux, R%d", m, i->simm13, i->rs1); ! 778: } ! 779: if(i->rs1 != i->rd) ! 780: bprint(i, ", R%d", i->rd); ! 781: } ! 782: ! 783: static void ! 784: cmp(Instr *i, char *m) ! 785: { ! 786: if(dascase || i->rd){ ! 787: add(i, m); ! 788: return; ! 789: } ! 790: if(i->i == 0) ! 791: bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2); ! 792: else ! 793: bprint(i, "CMP\tR%d, $%lux", i->rs1, i->simm13); ! 794: } ! 795: ! 796: static char *regtab[4] = { ! 797: "Y", ! 798: "PSR", ! 799: "WIM", ! 800: "TBR", ! 801: }; ! 802: ! 803: static void ! 804: wr(Instr *i, char *m) /* page 82 */ ! 805: { ! 806: if(dascase){ ! 807: if(i->i == 0) ! 808: bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2); ! 809: else ! 810: bprint(i, "%s\tR%d, $%lux", m, i->rs1, i->simm13); ! 811: }else{ ! 812: if(i->i && i->simm13==0) ! 813: bprint(i, "MOVW\tR%d", i->rs1); ! 814: else if(i->i == 0) ! 815: bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1); ! 816: else ! 817: bprint(i, "wr\t$%lux, R%d", i->simm13, i->rs1); ! 818: } ! 819: bprint(i, ", %s", regtab[i->op3&3]); ! 820: } ! 821: ! 822: static void ! 823: rd(Instr *i, char *m) /* page 103 */ ! 824: { ! 825: if(i->rs1==15 && i->rd==0){ ! 826: m = "stbar"; ! 827: if(!dascase) ! 828: m = "STBAR"; ! 829: bprint(i, "%s", m); ! 830: }else{ ! 831: if(!dascase) ! 832: m = "MOVW"; ! 833: bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd); ! 834: } ! 835: } ! 836: ! 837: static void ! 838: jmpl(Instr *i, char *m) /* page 82 */ ! 839: { ! 840: if(i->i == 0){ ! 841: if(i->rd == 15) ! 842: bprint(i, "%X\t(R%d+R%d)", "CALL", i->rs2, i->rs1); ! 843: else ! 844: bprint(i, "%X\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd); ! 845: }else{ ! 846: if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0) ! 847: bprint(i, "RETURN"); ! 848: else{ ! 849: bprint(i, "%X\t", m); ! 850: address(i); ! 851: bprint(i, ", R%d", i->rd); ! 852: } ! 853: } ! 854: } ! 855: ! 856: static void ! 857: loadf(Instr *i, char *m) /* page 70 */ ! 858: { ! 859: if(!dascase){ ! 860: m = "FMOVD"; ! 861: if(i->op3 == 0x20) ! 862: m = "FMOVF"; ! 863: else if(i->op3 == 0x21) ! 864: m = "MOVW"; ! 865: } ! 866: if(i->i == 0) ! 867: bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2); ! 868: else{ ! 869: bprint(i, "%s\t", m); ! 870: address(i); ! 871: } ! 872: if(i->op3 == 0x21) ! 873: bprint(i, ", FSR"); ! 874: else ! 875: bprint(i, ", R%d", i->rd); ! 876: } ! 877: ! 878: static ! 879: void storef(Instr *i, char *m) /* page 70 */ ! 880: { ! 881: if(!dascase){ ! 882: m = "FMOVD"; ! 883: if(i->op3 == 0x25 || i->op3 == 0x26) ! 884: m = "MOVW"; ! 885: else if(i->op3 == 0x20) ! 886: m = "FMOVF"; ! 887: } ! 888: bprint(i, "%s\t", m); ! 889: if(i->op3 == 0x25) ! 890: bprint(i, "FSR, "); ! 891: else if(i->op3 == 0x26) ! 892: bprint(i, "FQ, "); ! 893: else ! 894: bprint(i, "R%d, ", i->rd); ! 895: if(i->i == 0) ! 896: bprint(i, "(R%d+R%d)", i->rs1, i->rs2); ! 897: else ! 898: address(i); ! 899: } ! 900: ! 901: static ! 902: void loadc(Instr *i, char *m) /* page 72 */ ! 903: { ! 904: if(i->i == 0) ! 905: bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd); ! 906: else{ ! 907: bprint(i, "%s\t", m); ! 908: address(i); ! 909: bprint(i, ", C%d", i->rd); ! 910: } ! 911: } ! 912: ! 913: static ! 914: void loadcsr(Instr *i, char *m) /* page 72 */ ! 915: { ! 916: if(i->i == 0) ! 917: bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2); ! 918: else{ ! 919: bprint(i, "%s\t", m); ! 920: address(i); ! 921: bprint(i, ", CSR"); ! 922: } ! 923: } ! 924: ! 925: static struct{ ! 926: int opf; ! 927: char *name; ! 928: } fptab1[] = { /* ignores rs1 */ ! 929: 0xC4, "FITOS", /* page 109 */ ! 930: 0xC8, "FITOD", ! 931: 0xCC, "FITOX", ! 932: ! 933: 0xD1, "FSTOI", /* page 110 */ ! 934: 0xD2, "FDTOI", ! 935: 0xD3, "FXTOI", ! 936: ! 937: 0xC9, "FSTOD", /* page 111 */ ! 938: 0xCD, "FSTOX", ! 939: 0xC6, "FDTOS", ! 940: 0xCE, "FDTOX", ! 941: 0xC7, "FXTOS", ! 942: 0xCB, "FXTOD", ! 943: ! 944: 0x01, "FMOVS", /* page 112 */ ! 945: 0x05, "FNEGS", ! 946: 0x09, "FABSS", ! 947: ! 948: 0x29, "FSQRTS", /* page 113 */ ! 949: 0x2A, "FSQRTD", ! 950: 0x2B, "FSQRTX", ! 951: ! 952: 0, 0, ! 953: }; ! 954: ! 955: static struct{ ! 956: int opf; ! 957: char *name; ! 958: } fptab2[] = { /* uses rs1 */ ! 959: ! 960: 0x41, "FADDS", /* page 114 */ ! 961: 0x42, "FADDD", ! 962: 0x43, "FADDX", ! 963: 0x45, "FSUBS", ! 964: 0x46, "FSUBD", ! 965: 0x47, "FSUBX", ! 966: ! 967: 0x49, "FMULS", /* page 115 */ ! 968: 0x4A, "FMULD", ! 969: 0x4B, "FMULX", ! 970: 0x4D, "FDIVS", ! 971: 0x4E, "FDIVD", ! 972: 0x4F, "FDIVX", ! 973: ! 974: 0x51, "FCMPS", /* page 116 */ ! 975: 0x52, "FCMPD", ! 976: 0x53, "FCMPX", ! 977: 0x55, "FCMPES", ! 978: 0x56, "FCMPED", ! 979: 0x57, "FCMPEX", ! 980: ! 981: 0, 0 ! 982: }; ! 983: ! 984: static void ! 985: fpop(Instr *i, char *m) /* page 108-116 */ ! 986: { ! 987: int j; ! 988: ! 989: if(dascase==0 && i->size==2){ ! 990: bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd); ! 991: return; ! 992: } ! 993: for(j=0; fptab1[j].name; j++) ! 994: if(fptab1[j].opf == i->opf){ ! 995: bprint(i, "%X\tF%d, F%d", fptab1[j].name, i->rs2, i->rd); ! 996: return; ! 997: } ! 998: for(j=0; fptab2[j].name; j++) ! 999: if(fptab2[j].opf == i->opf){ ! 1000: bprint(i, "%X\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd); ! 1001: return; ! 1002: } ! 1003: bprint(i, "%X%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd); ! 1004: } ! 1005: ! 1006: static int ! 1007: sparcfoll(Map *map, ulong pc, Rgetter rget, ulong *foll) ! 1008: { ! 1009: ulong w, r1, r2; ! 1010: char buf[8]; ! 1011: Instr i; ! 1012: ! 1013: mymap = map; ! 1014: if (mkinstr(pc, &i) < 0) ! 1015: return -1; ! 1016: w = i.w0; ! 1017: switch(w & 0xC1C00000){ ! 1018: case 0x00800000: /* branch on int cond */ ! 1019: case 0x01800000: /* branch on fp cond */ ! 1020: case 0x01C00000: /* branch on copr cond */ ! 1021: foll[0] = pc+8; ! 1022: foll[1] = pc + (i.simmdisp22<<2); ! 1023: return 2; ! 1024: } ! 1025: ! 1026: if((w&0xC0000000) == 0x40000000){ /* CALL */ ! 1027: foll[0] = pc + (i.disp30<<2); ! 1028: return 1; ! 1029: } ! 1030: ! 1031: if((w&0xC1F80000) == 0x81C00000){ /* JMPL */ ! 1032: sprint(buf, "R%d", (w>>14)&0xF); ! 1033: r1 = (*rget)(map, buf); ! 1034: if(w & 0x2000) /* JMPL R1+simm13 */ ! 1035: r2 = i.simm13; ! 1036: else{ /* JMPL R1+R2 */ ! 1037: sprint(buf, "R%d", w&0xF); ! 1038: r2 = (*rget)(map, buf); ! 1039: } ! 1040: foll[0] = r1 + r2; ! 1041: return 1; ! 1042: } ! 1043: foll[0] = pc+i.size*4; ! 1044: return 1; ! 1045: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.