|
|
1.1 ! root 1: #include <u.h> ! 2: #include <libc.h> ! 3: #include <bio.h> ! 4: #include <mach.h> ! 5: ! 6: /* ! 7: * i960-specific debugger interface ! 8: * i960 has an as yet unknown stack format - presotto ! 9: */ ! 10: ! 11: static char *i960excep(Map*, Rgetter); ! 12: static int i960inst(Map*, ulong, char, char*, int); ! 13: static int i960das(Map*, ulong, char*, int); ! 14: static int i960foll(Map*, ulong, Rgetter, ulong*); ! 15: static int i960instlen(Map*, ulong); ! 16: ! 17: Machdata i960mach = ! 18: { ! 19: {0x66, 0, 0x06, 0}, /* break point: fmark */ ! 20: 4, /* break point size */ ! 21: ! 22: leswab, /* convert short to local byte order */ ! 23: leswal, /* convert long to local byte order */ ! 24: cisctrace, /* C traceback */ ! 25: ciscframe, /* frame finder */ ! 26: 0, /* ublock fixup */ ! 27: i960excep, /* print exception */ ! 28: 0, /* breakpoint fixup */ ! 29: leieeesftos, /* single precision float printer */ ! 30: leieeedftos, /* double precision float printer */ ! 31: i960foll, /* following addresses */ ! 32: i960inst, /* print instruction */ ! 33: i960das, /* dissembler */ ! 34: i960instlen, /* 0 */ ! 35: }; ! 36: ! 37: static char* ! 38: i960excep(Map *map, Rgetter rget) ! 39: { ! 40: USED(map, rget); ! 41: return "intel machine exceptions are too hard to decode"; ! 42: } ! 43: ! 44: /* I960 disassembler and related functions */ ! 45: ! 46: typedef struct Instr Instr; ! 47: typedef struct Opcode Opcode; ! 48: ! 49: /* ! 50: * operand types ! 51: */ ! 52: enum ! 53: { ! 54: EA=1, ! 55: R1, R2, R3, ! 56: S1, S2, S3, ! 57: IR1, IR2, IR3, ! 58: }; ! 59: ! 60: enum ! 61: { ! 62: Treg, ! 63: Tctrl, ! 64: Tcobr, ! 65: Tmem, ! 66: }; ! 67: ! 68: ! 69: struct Opcode ! 70: { ! 71: ushort code; ! 72: char *name; ! 73: uchar and[3]; ! 74: }; ! 75: ! 76: struct Instr ! 77: { ! 78: Opcode *op; /* opcode line */ ! 79: ulong mem[2]; /* memory for this instruction */ ! 80: int n; /* # longs for this instruction */ ! 81: char and[3][64]; ! 82: ulong rel; ! 83: char *err; ! 84: ! 85: int type; ! 86: int index; ! 87: int base; ! 88: int mult; ! 89: char *curr; /* fill point in output buffer */ ! 90: char *end; /* end of output buffer */ ! 91: ulong addr; /* pc of instruction */ ! 92: }; ! 93: ! 94: static Map* mymap; ! 95: ! 96: Opcode optab[] = { ! 97: { 0x08, "B", EA }, ! 98: { 0x09, "CALL", EA }, ! 99: { 0x0A, "RET" }, ! 100: { 0x0B, "BAL", EA }, ! 101: { 0x10, "BNO", EA }, ! 102: { 0x11, "BG", EA }, ! 103: { 0x12, "BE", EA }, ! 104: { 0x13, "BGE", EA }, ! 105: { 0x14, "BL", EA }, ! 106: { 0x15, "BNE", EA }, ! 107: { 0x16, "BLE", EA }, ! 108: { 0x17, "BO", EA }, ! 109: { 0x18, "FAULTNO" }, ! 110: { 0x19, "FAULTG" }, ! 111: { 0x1A, "FAULTE" }, ! 112: { 0x1B, "FAULTGE" }, ! 113: { 0x1C, "FAULTL" }, ! 114: { 0x1D, "FAULTNE" }, ! 115: { 0x1E, "FAULTLE" }, ! 116: { 0x1F, "FAULTO" }, ! 117: { 0x20, "TESTNO", R1 }, ! 118: { 0x21, "TESTG", R1 }, ! 119: { 0x22, "TESTE", R1 }, ! 120: { 0x23, "TESTGE", R1 }, ! 121: { 0x24, "TESTL", R1 }, ! 122: { 0x25, "TESTNE", R1 }, ! 123: { 0x26, "TESTLE", R1 }, ! 124: { 0x27, "TESTO", R1 }, ! 125: { 0x30, "BBC", S1, R2, EA }, ! 126: { 0x31, "CMPOBG", S1, R2, EA }, ! 127: { 0x32, "CMPOBE", S1, R2, EA }, ! 128: { 0x33, "CMPOBGE", S1, R2, EA }, ! 129: { 0x34, "CMPOBL", S1, R2, EA }, ! 130: { 0x35, "CMPOBNE", S1, R2, EA }, ! 131: { 0x36, "CMPOBLE", S1, R2, EA }, ! 132: { 0x37, "CMPOBO", S1, R2, EA }, ! 133: { 0x38, "CMPIBNO", S1, R2, EA }, ! 134: { 0x39, "CMPIBG", S1, R2, EA }, ! 135: { 0x3A, "CMPIBE", S1, R2, EA }, ! 136: { 0x3B, "CMPIBGE", S1, R2, EA }, ! 137: { 0x3C, "CMPIBL", S1, R2, EA }, ! 138: { 0x3D, "CMPIBNE", S1, R2, EA }, ! 139: { 0x3E, "CMPIBLE", S1, R2, EA }, ! 140: { 0x3F, "CMPIBO", S1, R2, EA }, ! 141: { 0x80, "MOVOB", EA, R1 }, ! 142: { 0x82, "MOVOB", R1, EA }, ! 143: { 0x84, "B", EA }, ! 144: { 0x85, "BAL", EA, R1 }, ! 145: { 0x86, "CALL", EA }, ! 146: { 0x88, "MOVOS", EA, R1 }, ! 147: { 0x8A, "MOVOS", R1, EA }, ! 148: { 0x8C, "LDA", EA, R1 }, ! 149: { 0x90, "MOV", EA, R1 }, ! 150: { 0x92, "MOV", R1, EA }, ! 151: { 0x98, "MOVV", EA, R1 }, ! 152: { 0x9A, "MOVV", R1, EA }, ! 153: { 0xA0, "MOVT", EA, R1 }, ! 154: { 0xA2, "MOVT", R1, EA }, ! 155: { 0xB0, "MOVQ", EA, R1 }, ! 156: { 0xB2, "MOVQ", R1, EA }, ! 157: { 0xC0, "MOVIB", EA, R1 }, ! 158: { 0xC2, "MOVIB", R1, EA }, ! 159: { 0xC8, "MOVIS", EA, R1 }, ! 160: { 0xCA, "MOVIS", R1, EA }, ! 161: { 0x580, "NOTBIT", S1, S2, R3 }, ! 162: { 0x581, "AND", S1, S2, R3 }, ! 163: { 0x582, "ANDNOT", S1, S2, R3 }, ! 164: { 0x583, "SETBIT", S1, S2, R3 }, ! 165: { 0x584, "NOTAND", S1, R3 }, ! 166: { 0x586, "XOR", S1, S2, R3 }, ! 167: { 0x587, "OR", S1, S2, R3 }, ! 168: { 0x588, "NOR", S1, S2, R3 }, ! 169: { 0x589, "XNOR", S1, S2, R3 }, ! 170: { 0x58A, "NOT", S1, R3 }, ! 171: { 0x58B, "ORNOT", S1, S2, R3 }, ! 172: { 0x58C, "CLRBIT", S1, S2, R3 }, ! 173: { 0x58D, "NOTOR", S1, S2, R3 }, ! 174: { 0x58E, "NAND", S1, S2, R3 }, ! 175: { 0x58F, "ALTERBIT", S1, S2, R3 }, ! 176: { 0x590, "ADDO", S1, S2, R3 }, ! 177: { 0x591, "ADDI", S1, S2, R3 }, ! 178: { 0x592, "SUBO", S1, S2, R3 }, ! 179: { 0x593, "SUBI", S1, S2, R3 }, ! 180: { 0x598, "SHRO", S1, S2, R3 }, ! 181: { 0x59A, "SHRDI", S1, S2, R3 }, ! 182: { 0x59B, "SHRI", S1, S2, R3 }, ! 183: { 0x59C, "SHLO", S1, S2, R3 }, ! 184: { 0x59D, "ROTATE", S1, S2, R3 }, ! 185: { 0x59E, "SHLI", S1, S2, R3 }, ! 186: { 0x5A0, "CMPO", S1, S2 }, ! 187: { 0x5A1, "CMPI", S1, S2 }, ! 188: { 0x5A2, "CONCMPO", S1, S2 }, ! 189: { 0x5A3, "CONCMPI", S1, S2 }, ! 190: { 0x5A4, "CMPINCI", S1, S2, R3 }, ! 191: { 0x5A5, "CMPINCO", S1, S2, R3 }, ! 192: { 0x5A6, "CMPDECI", S1, S2, R3 }, ! 193: { 0x5A7, "CMPDECO", S1, S2, R3 }, ! 194: { 0x5AC, "SCANBYTE", S1, S2 }, ! 195: { 0x5AE, "CHKBIT", S1, S2 }, ! 196: { 0x5B0, "ADDC", S1, S2, R3 }, ! 197: { 0x5B2, "SUBC", S1, S2, R3 }, ! 198: { 0x5CC, "MOV", S1, R3 }, ! 199: { 0x5DC, "MOVV", S1, R3 }, ! 200: { 0x5EC, "MOVT", S1, R3 }, ! 201: { 0x5FC, "MOVQ", S1, R3 }, ! 202: { 0x600, "SYNMOV", IR1, IR3 }, ! 203: { 0x601, "SYNMOVV", IR1, IR3 }, ! 204: { 0x602, "SYNMOVQ", IR1, IR3 }, ! 205: { 0x610, "ATMOD", IR1, S2, R3 }, ! 206: { 0x612, "ATADD", IR1, S2, R3 }, ! 207: { 0x615, "SYNMOV", IR1, R2 }, ! 208: { 0x640, "SPANBIT", S1, R2 }, ! 209: { 0x641, "SCANBIT", S1, R2 }, ! 210: { 0x642, "DADDC", S1, S2, R3 }, ! 211: { 0x643, "DSUBC", S1, S2, R3 }, ! 212: { 0x644, "DMOVT", S1, R2 }, ! 213: { 0x645, "MODAC", S1, S2, R3 }, ! 214: { 0x650, "MODIFY", S1, S2, R3 }, ! 215: { 0x651, "EXTRACT", S1, S2, R3 }, ! 216: { 0x654, "MODTC", S1, S2, R3 }, ! 217: { 0x655, "MODPC", S1, S2 }, ! 218: { 0x660, "CALLS", S1 }, ! 219: { 0x66B, "MARK" }, ! 220: { 0x66C, "FMARK" }, ! 221: { 0x66D, "FLUSHREG" }, ! 222: { 0x66F, "SYNCF" }, ! 223: { 0x670, "EMUL", S1, S2, R3 }, ! 224: { 0x671, "EDIV", S1, S2, R3 }, ! 225: { 0x674, "CVTIF", S1, R2 }, ! 226: { 0x675, "CVTILF", S1, R2 }, ! 227: { 0x676, "SCALED", S1, S2, R3 }, ! 228: { 0x677, "SCALEF", S1, S2, R3 }, ! 229: { 0x680, "ATANF", S1, S2, R3 }, ! 230: { 0x681, "LOGEPF", S1, S2, R3 }, ! 231: { 0x682, "LOGF", S1, S2, R3 }, ! 232: { 0x683, "REMF", S1, S2, R3 }, ! 233: { 0x684, "CMPOF", S1, S2 }, ! 234: { 0x685, "CMPF", S1, S2 }, ! 235: { 0x688, "SQRTF", S1, R2 }, ! 236: { 0x689, "EXPF", S1, R2 }, ! 237: { 0x68A, "LOGBNTF", S1, R2 }, ! 238: { 0x68B, "ROUNDF", S1, R2 }, ! 239: { 0x68C, "SINF", S1, R2 }, ! 240: { 0x68D, "COSF", S1, R2 }, ! 241: { 0x68E, "TANF", S1, R2 }, ! 242: { 0x68F, "CLASSF", S1 }, ! 243: { 0x690, "ATAND", S1, S2, R3 }, ! 244: { 0x691, "LOGEPD", S1, S2, R3 }, ! 245: { 0x692, "LOGD", S1, S2, R3 }, ! 246: { 0x693, "REMD", S1, S2, R3 }, ! 247: { 0x694, "CMPOD", S1, S2 }, ! 248: { 0x695, "CMPD", S1, S2 }, ! 249: { 0x698, "SQRTD", S1, S2 }, ! 250: { 0x699, "EXPD", S1, S2 }, ! 251: { 0x69A, "LOGBND", S1, S2 }, ! 252: { 0x69B, "ROUNDD", S1, S2 }, ! 253: { 0x69C, "SIND", S1, S2 }, ! 254: { 0x69D, "COSD", S1, S2 }, ! 255: { 0x69E, "TAND", S1, S2 }, ! 256: { 0x69F, "CLASSD", S1 }, ! 257: { 0x6C0, "CVTRI", S1, R2 }, ! 258: { 0x6C1, "CVTRI", S1, R2 }, ! 259: { 0x6C2, "CVTRI", S1, R2 }, ! 260: { 0x6C3, "CVTRI", S1, R2 }, ! 261: { 0x6C9, "MOVF", S1, R2 }, ! 262: { 0x6D9, "MOVD", S1, R2 }, ! 263: { 0x6E2, "CPYSRE", S1, S2, R3 }, ! 264: { 0x6E3, "CPYRSRE", S1, S2, R3 }, ! 265: { 0x6E3, "MOVRE", S1, R2 }, ! 266: { 0x701, "MULO", S1, S2, R3 }, ! 267: { 0x708, "REMO", S1, S2, R3 }, ! 268: { 0x70B, "DIVO", S1, S2, R3 }, ! 269: { 0x741, "MULI", S1, S2, R3 }, ! 270: { 0x748, "REMI", S1, S2, R3 }, ! 271: { 0x749, "MODI", S1, S2, R3 }, ! 272: { 0x74B, "DIVI", S1, S2, R3 }, ! 273: { 0x78B, "DIVF", S1, S2, R3 }, ! 274: { 0x78C, "MULF", S1, S2, R3 }, ! 275: { 0x78D, "SUBF", S1, S2, R3 }, ! 276: { 0x78F, "ADDR", S1, S2, R3 }, ! 277: { 0x79B, "DIVD", S1, S2, R3 }, ! 278: { 0x79C, "MULD", S1, S2, R3 }, ! 279: { 0x79D, "SUBD", S1, S2, R3 }, ! 280: { 0x79F, "MODI", S1, S2, R3 }, ! 281: { 0 }, ! 282: }; ! 283: #define NOP (sizeof(optab)/sizeof(Opcode)) ! 284: ! 285: /* ! 286: * get an instruction long ! 287: */ ! 288: static int ! 289: igetl(Instr *ip, long *lp) ! 290: { ! 291: if(ip->n >= 2){ ! 292: werrstr("instruction too big"); ! 293: return -1; ! 294: } ! 295: if (get4(mymap, ip->addr+ip->n*4, (long*) &ip->mem[ip->n]) < 0) { ! 296: werrstr("can't read instruction: %r"); ! 297: return -1; ! 298: } ! 299: *lp = ip->mem[ip->n++]; ! 300: return 1; ! 301: } ! 302: ! 303: static Opcode* ! 304: findopcode(ushort code) ! 305: { ! 306: Opcode *o; ! 307: ! 308: for(o = optab; o->code; o++) ! 309: if(code == o->code) ! 310: return o; ! 311: werrstr("unknown opcode"); ! 312: return 0; ! 313: } ! 314: ! 315: static char* ! 316: genname(ulong l, int reg, int mode, int regonly, int ind) ! 317: { ! 318: static char name[32]; ! 319: ! 320: reg = (l>>reg) & 0x1f; ! 321: if(mode >= 0) ! 322: mode = (l>>mode) & 1; ! 323: else ! 324: mode = 0; ! 325: if(mode) ! 326: sprint(name, regonly?"?$%d?":"$%d", reg); ! 327: else ! 328: sprint(name, ind?"(R%d)":"R%d", reg); ! 329: return name; ! 330: } ! 331: ! 332: /* ! 333: * decode a reg instruction ! 334: */ ! 335: static char* ! 336: regfield(Instr *ip, uchar and, ulong l) ! 337: { ! 338: switch(and){ ! 339: case S1: ! 340: case R1: ! 341: case IR1: ! 342: return genname(l, 0, 11, and!=S1, and==IR1); ! 343: case S2: ! 344: case R2: ! 345: case IR2: ! 346: return genname(l, 14, 12, and!=S2, and==IR2); ! 347: case S3: ! 348: case R3: ! 349: case IR3: ! 350: return genname(l, 19, 13, and!=S3, and==IR3); ! 351: default: ! 352: ip->err = "missing regfield"; ! 353: return("???"); ! 354: } ! 355: } ! 356: ! 357: static void ! 358: chk56(Instr *ip, ulong l) ! 359: { ! 360: if(l & (3<<5)) ! 361: ip->err = "bits 5 and 6 not 0"; ! 362: } ! 363: ! 364: static int ! 365: reginst(Instr *ip, ulong l) ! 366: { ! 367: ushort code; ! 368: int i; ! 369: ! 370: ip->type = Treg; ! 371: code = ((l>>20)&0xff0) | ((l>>7)&0xf); ! 372: ip->op = findopcode(code); ! 373: if(ip->op == 0) ! 374: return -1; ! 375: for(i = 0; i < 3; i++){ ! 376: if(ip->op->and[i] == 0) ! 377: break; ! 378: strcpy(ip->and[i], regfield(ip, ip->op->and[i], l)); ! 379: } ! 380: return 0; ! 381: } ! 382: ! 383: /* ! 384: * decode a control and branch instruction ! 385: */ ! 386: static char* ! 387: cobrfield(Instr *ip, uchar and, ulong l) ! 388: { ! 389: long disp; ! 390: ! 391: switch(and){ ! 392: case S1: ! 393: case R1: ! 394: case IR1: ! 395: return genname(l, 19, 13, and!=S1, and==IR1); ! 396: case R2: ! 397: case IR2: ! 398: return genname(l, 14, -1, 1, and==IR2); ! 399: case EA: ! 400: if(l & (1<<12)) ! 401: disp = -(((~l) & 0xfff)+1); ! 402: else ! 403: disp = l & 0xfff; ! 404: ip->rel = ip->addr + 4 + disp; ! 405: return ".+"; ! 406: default: ! 407: return "???"; ! 408: } ! 409: } ! 410: static int ! 411: cobrinst(Instr *ip, ulong l) ! 412: { ! 413: ushort code; ! 414: int i; ! 415: ! 416: ip->type = Tcobr; ! 417: if(l&3) ! 418: ip->err = "disp not mult of 4"; ! 419: code = l>>24; ! 420: ip->op = findopcode(code); ! 421: if(ip->op == 0) ! 422: return -1; ! 423: for(i = 0; i < 3; i++){ ! 424: if(ip->op->and[i] == 0) ! 425: break; ! 426: strcpy(ip->and[i], cobrfield(ip, ip->op->and[i], l)); ! 427: } ! 428: return 0; ! 429: } ! 430: ! 431: /* ! 432: * decode a control instruction ! 433: */ ! 434: static int ! 435: ctrlinst(Instr *ip, ulong l) ! 436: { ! 437: ushort code; ! 438: long disp; ! 439: ! 440: ip->type = Tctrl; ! 441: if(l&3) ! 442: ip->err = "disp not mult of 4"; ! 443: code = l>>24; ! 444: ip->op = findopcode(code); ! 445: if(ip->op == 0) ! 446: return -1; ! 447: if(ip->op->and[0] == 0) ! 448: return 0; ! 449: if(l & (1<<23)) ! 450: disp = -(((~l) & 0x7fffff)+1); ! 451: else ! 452: disp = l & 0x7fffff; ! 453: ip->rel = ip->addr + 4 + disp; ! 454: strcpy(ip->and[0], ".+"); ! 455: return 0; ! 456: } ! 457: ! 458: static int ! 459: sprintoff(char *addr, int n, char *fmt, ulong v) ! 460: { ! 461: Symbol s; ! 462: long w; ! 463: ! 464: w = v+mach->sb; ! 465: if (findsym(w, CDATA, &s)) { ! 466: w = s.value-w; ! 467: if (w <= 4096) { ! 468: if (w) ! 469: return snprint(addr, n, "%s+%lux(SB)", s.name, w); ! 470: else ! 471: return snprint(addr, n, "%s(SB)", s.name); ! 472: } ! 473: } ! 474: return snprint(addr, n, fmt, v); ! 475: } ! 476: ! 477: /* ! 478: * decode a memory instruction ! 479: */ ! 480: static char* ! 481: memfield(Instr *ip, uchar and, ulong l) ! 482: { ! 483: long disp; ! 484: static char addr[64]; ! 485: int abase; ! 486: int scale; ! 487: int index; ! 488: ! 489: ip->mult = 1; ! 490: switch(and){ ! 491: case R1: ! 492: case IR1: ! 493: return genname(l, 19, -1, 1, and==IR1); ! 494: case EA: ! 495: abase = (l>>14)&0x1f; ! 496: scale = 1 << ((l>>7)&0x7); ! 497: index = l & 0x1f; ! 498: switch((l>>10)&0xf){ ! 499: case 0x4: ! 500: chk56(ip, l); ! 501: ip->base = abase + 1; ! 502: sprint(addr, "(R%d)", abase); ! 503: break; ! 504: case 0x5: ! 505: chk56(ip, l); ! 506: if (igetl(ip, &disp) < 0) { ! 507: strcpy(addr, "???"); ! 508: break; ! 509: } ! 510: ip->rel = disp + ip->addr + 8; ! 511: strcpy(addr, ".+"); ! 512: break; ! 513: case 0x6: ! 514: strcpy(addr, "???"); ! 515: break; ! 516: case 0x7: ! 517: chk56(ip, l); ! 518: ip->base = abase + 1; ! 519: ip->mult = scale; ! 520: ip->index = index + 1; ! 521: sprint(addr, "(R%d)(%d*R%d)", abase, scale, index); ! 522: break; ! 523: case 0xc: ! 524: chk56(ip, l); ! 525: if (igetl(ip, &disp) < 0) { ! 526: strcpy(addr, "???"); ! 527: break; ! 528: } ! 529: ip->rel = disp; ! 530: strcpy(addr, ".+"); ! 531: break; ! 532: case 0xd: ! 533: chk56(ip, l); ! 534: if (igetl(ip, &disp) < 0) { ! 535: strcpy(addr, "???"); ! 536: break; ! 537: } ! 538: ip->rel = disp; ! 539: if(abase == 28) ! 540: sprintoff(addr, sizeof(addr), "%lux(R28)", disp); ! 541: else{ ! 542: ip->base = abase + 1; ! 543: sprint(addr, "%lx(R%d)", disp, abase); ! 544: } ! 545: break; ! 546: case 0xe: ! 547: chk56(ip, l); ! 548: if (igetl(ip, &disp) < 0) { ! 549: strcpy(addr, "???"); ! 550: break; ! 551: } ! 552: ip->rel = disp; ! 553: ip->mult = scale; ! 554: ip->index = index + 1; ! 555: sprint(addr, "%lx(%d*R%d)", disp, scale, index); ! 556: break; ! 557: case 0xf: ! 558: chk56(ip, l); ! 559: if (igetl(ip, &disp) < 0) { ! 560: strcpy(addr, "???"); ! 561: break; ! 562: } ! 563: ip->rel = disp; ! 564: ip->mult = scale; ! 565: ip->index = index + 1; ! 566: ip->base = abase + 1; ! 567: sprint(addr, "%lx(R%d)(%d*R%d)", disp, abase, ! 568: scale, index); ! 569: break; ! 570: default: ! 571: disp = l&0xfff; ! 572: ip->rel = disp; ! 573: if(l & (1<<13)){ ! 574: if(abase == 28) ! 575: sprintoff(addr, sizeof(addr), "%lux(R28)", disp); ! 576: else{ ! 577: ip->base = abase + 1; ! 578: sprint(addr, "%lux(R%d)", disp, abase); ! 579: } ! 580: } else { ! 581: strcpy(addr, ".+"); ! 582: } ! 583: break; ! 584: } ! 585: return addr; ! 586: default: ! 587: break; ! 588: } ! 589: return "???"; ! 590: } ! 591: static int ! 592: meminst(Instr *ip, ulong l) ! 593: { ! 594: ushort code; ! 595: int i; ! 596: ! 597: ip->type = Tmem; ! 598: code = l>>24; ! 599: ip->op = findopcode(code); ! 600: if(ip->op == 0) ! 601: return -1; ! 602: for(i = 0; i < 2; i++){ ! 603: if(ip->op->and[i] == 0) ! 604: break; ! 605: strcpy(ip->and[i], memfield(ip, ip->op->and[i], l)); ! 606: } ! 607: return 0; ! 608: } ! 609: ! 610: static int ! 611: mkinstr(Instr *ip, ulong pc) ! 612: { ! 613: long l; ! 614: ! 615: memset(ip, 0, sizeof(Instr)); ! 616: ip->addr = pc; ! 617: if (igetl(ip, &l) < 0) ! 618: return -1; ! 619: switch(l>>28){ ! 620: case 0x0: ! 621: case 0x1: ! 622: return ctrlinst(ip, l); ! 623: case 0x2: ! 624: case 0x3: ! 625: return cobrinst(ip, l); ! 626: case 0x5: ! 627: case 0x6: ! 628: case 0x7: ! 629: return reginst(ip, l); ! 630: case 0x8: ! 631: case 0x9: ! 632: case 0xa: ! 633: case 0xb: ! 634: case 0xc: ! 635: return meminst(ip, l); ! 636: } ! 637: werrstr("unknown opcode"); ! 638: return -1; ! 639: } ! 640: ! 641: static int ! 642: i960inst(Map *map, ulong pc, char modifier, char *buf, int n) ! 643: { ! 644: Instr instr; ! 645: int i; ! 646: char *and; ! 647: char *end; ! 648: ! 649: USED(modifier); ! 650: mymap = map; ! 651: if(mkinstr(&instr, pc) < 0) ! 652: return -1; ! 653: ! 654: end = buf+n-1; ! 655: buf += snprint(buf, end-buf, "%s ", instr.op->name); ! 656: for(i = 0; i < 3; i++){ ! 657: and = instr.and[i]; ! 658: if(*and == 0) ! 659: break; ! 660: if(i != 0) ! 661: buf += snprint(buf, end-buf, ","); ! 662: if(strcmp(and, ".+") == 0){ ! 663: buf += sprintoff(buf, end-buf, "$%lux", instr.rel); ! 664: } else ! 665: buf += snprint(buf, end-buf, "%s", and); ! 666: } ! 667: ! 668: if(instr.err) ! 669: snprint(buf, end-buf, "\t\t;%s", instr.err); ! 670: ! 671: return instr.n*4; ! 672: } ! 673: ! 674: static int ! 675: i960das(Map *map, ulong pc, char *buf, int n) ! 676: { ! 677: Instr instr; ! 678: ! 679: mymap = map; ! 680: if (mkinstr(&instr, pc) < 0) ! 681: return -1; ! 682: if (n > 8) { ! 683: _hexify(buf, instr.mem[0], 7); ! 684: n -= 8; ! 685: buf += 8; ! 686: } ! 687: if (n > 9 && instr.n == 2) { ! 688: *buf++ = ' '; ! 689: _hexify(buf, instr.mem[1], 7); ! 690: buf += 8; ! 691: } ! 692: *buf = 0; ! 693: return instr.n*4; ! 694: } ! 695: ! 696: static int ! 697: i960instlen(Map *map, ulong pc) ! 698: { ! 699: Instr instr; ! 700: ! 701: mymap = map; ! 702: if (mkinstr(&instr, pc) < 0) ! 703: return -1; ! 704: return instr.n*4; ! 705: } ! 706: ! 707: static int ! 708: i960foll(Map *map, ulong pc, Rgetter rget, ulong *foll) ! 709: { ! 710: Instr instr; ! 711: ulong l; ! 712: char buf[8]; ! 713: ! 714: mymap = map; ! 715: if (mkinstr(&instr, pc) < 0) ! 716: return -1; ! 717: foll[0] = pc + instr.n; ! 718: switch(instr.type){ ! 719: case Tcobr: ! 720: case Treg: ! 721: break; ! 722: case Tctrl: ! 723: if(instr.op->name[0] == 'B'){ ! 724: foll[1] = instr.rel; ! 725: return 2; ! 726: } ! 727: if(strcmp("CALL", instr.op->name) == 0){ ! 728: foll[0] = instr.rel; ! 729: return 1; ! 730: } ! 731: if(strcmp("RET", instr.op->name) == 0) ! 732: return -1; ! 733: break; ! 734: case Tmem: ! 735: if(strcmp("BAL", instr.op->name) == 0 ! 736: || strcmp("CALL", instr.op->name) == 0){ ! 737: l = instr.rel; ! 738: if(instr.index){ ! 739: sprint(buf, "R%d", instr.index - 1); ! 740: l += (*rget)(map, buf) * instr.mult; ! 741: } ! 742: if(instr.base){ ! 743: sprint(buf, "R%d", instr.base - 1); ! 744: l += (*rget)(map, buf); ! 745: } ! 746: foll[0] = l; ! 747: return 1; ! 748: } ! 749: break; ! 750: } ! 751: return 1; ! 752: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.