Annotation of sys/arch/m88k/m88k/db_disasm.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: db_disasm.c,v 1.8 2006/05/04 19:32:21 miod Exp $ */
! 2: /*
! 3: * Copyright (c) 2006, Miodrag Vallat
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: *
! 14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 15: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 16: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 17: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 18: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 19: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 20: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 22: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 23: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 24: * POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26: /*
! 27: * Mach Operating System
! 28: * Copyright (c) 1993-1991 Carnegie Mellon University
! 29: * Copyright (c) 1991 OMRON Corporation
! 30: * All Rights Reserved.
! 31: *
! 32: * Permission to use, copy, modify and distribute this software and its
! 33: * documentation is hereby granted, provided that both the copyright
! 34: * notice and this permission notice appear in all copies of the
! 35: * software, derivative works or modified versions, and any portions
! 36: * thereof, and that both notices appear in supporting documentation.
! 37: *
! 38: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 39: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
! 40: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 41: *
! 42: * Carnegie Mellon requests users of this software to return to
! 43: *
! 44: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 45: * School of Computer Science
! 46: * Carnegie Mellon University
! 47: * Pittsburgh PA 15213-3890
! 48: *
! 49: * any improvements or extensions that they make and grant Carnegie the
! 50: * rights to redistribute these changes.
! 51: */
! 52:
! 53: /*
! 54: * m88k disassembler for use in ddb
! 55: */
! 56:
! 57: #include <sys/param.h>
! 58: #include <sys/systm.h>
! 59:
! 60: #include <machine/db_machdep.h>
! 61:
! 62: #include <ddb/db_sym.h> /* DB_STGY_PROC, db_printsym() */
! 63: #include <ddb/db_access.h> /* db_get_value() */
! 64: #include <ddb/db_output.h> /* db_printf() */
! 65: #include <ddb/db_interface.h>
! 66:
! 67: void oimmed(int, u_int32_t, const char *, vaddr_t);
! 68: void ctrlregs(int, u_int32_t, const char *, vaddr_t);
! 69: void sindou(int, u_int32_t, const char *, vaddr_t);
! 70: void jump(int, u_int32_t, const char *, vaddr_t);
! 71: void instset(int, u_int32_t, const char *, vaddr_t);
! 72: void obranch(int, u_int32_t, const char *, vaddr_t);
! 73: void brcond(int, u_int32_t, const char *, vaddr_t);
! 74: void otrap(int, u_int32_t, const char *, vaddr_t);
! 75: void obit(int, u_int32_t, const char *, vaddr_t);
! 76: void bitman(int, u_int32_t, const char *, vaddr_t);
! 77: void immem(int, u_int32_t, const char *, vaddr_t);
! 78: void nimmem(int, u_int32_t, const char *, vaddr_t);
! 79: void lognim(int, u_int32_t, const char *, vaddr_t);
! 80: void onimmed(int, u_int32_t, const char *, vaddr_t);
! 81: void pinst(int, u_int32_t, const char *, vaddr_t);
! 82:
! 83: void printcmp(int, u_int);
! 84: void printcond(u_int);
! 85: void symofset(u_int, u_int, vaddr_t);
! 86: const char *cregname(int, u_int, u_int);
! 87:
! 88: /*
! 89: * Common instruction modifiers
! 90: */
! 91:
! 92: static const char *instwidth[] = {
! 93: ".d", " ", ".h", ".b", ".x" /* see nimmem() for use of last value */
! 94: };
! 95: static const char *xinstwidth[4] = {
! 96: ".d", " ", ".x", ".?"
! 97: };
! 98: static const char *cmpname[] = {
! 99: NULL,
! 100: NULL,
! 101: "eq",
! 102: "ne",
! 103: "gt",
! 104: "le",
! 105: "lt",
! 106: "ge",
! 107: "hi",
! 108: "ls",
! 109: "lo",
! 110: "hs",
! 111: "be",
! 112: "nb",
! 113: "he",
! 114: "nh"
! 115: };
! 116: static const char *condname[0x1f] = {
! 117: NULL,
! 118: "gt", /* 00001 */
! 119: "eq", /* 00010 */
! 120: "ge", /* 00011 */
! 121: NULL,
! 122: NULL,
! 123: NULL,
! 124: NULL,
! 125: NULL,
! 126: NULL,
! 127: NULL,
! 128: NULL,
! 129: "lt", /* 01100 */
! 130: "ne", /* 01101 */
! 131: "le" /* 01110 */
! 132: };
! 133: static const char sodname[4] = "sdx?";
! 134:
! 135: /*
! 136: * Descriptive control register names
! 137: */
! 138:
! 139: static const char *m88100_ctrlreg[2][64] = {
! 140: { /* main unit */
! 141: "PID",
! 142: "PSR",
! 143: "EPSR",
! 144: "SSBR",
! 145: "SXIP",
! 146: "SNIP",
! 147: "SFIP",
! 148: "VBR",
! 149: "DMT0",
! 150: "DMD0",
! 151: "DMA0",
! 152: "DMT1",
! 153: "DMD1",
! 154: "DMA1",
! 155: "DMT2",
! 156: "DMD2",
! 157: "DMA2",
! 158: "SR0",
! 159: "SR1",
! 160: "SR2",
! 161: "SR3",
! 162: },
! 163: { /* SFU1 = FPU */
! 164: "FPECR",
! 165: "FPHS1",
! 166: "FPLS1",
! 167: "FPHS2",
! 168: "FPLS2",
! 169: "FPPT",
! 170: "FPRH",
! 171: "FPRL",
! 172: "FPIT",
! 173: NULL, NULL,
! 174: NULL, NULL, NULL, NULL, NULL,
! 175: NULL, NULL, NULL, NULL, NULL,
! 176: NULL, NULL, NULL, NULL, NULL,
! 177: NULL, NULL, NULL, NULL, NULL,
! 178: NULL, NULL, NULL, NULL, NULL,
! 179: NULL, NULL, NULL, NULL, NULL,
! 180: NULL, NULL, NULL, NULL, NULL,
! 181: NULL, NULL, NULL, NULL, NULL,
! 182: NULL, NULL, NULL, NULL, NULL,
! 183: NULL, NULL, NULL, NULL, NULL,
! 184: NULL,
! 185: "FPSR",
! 186: "FPCR"
! 187: }
! 188: };
! 189:
! 190: static const char *m88110_ctrlreg[2][64] = {
! 191: { /* main unit */
! 192: "PID",
! 193: "PSR",
! 194: "EPSR",
! 195: NULL,
! 196: "EXIP",
! 197: "ENIP",
! 198: NULL,
! 199: "VBR",
! 200: NULL,
! 201: NULL,
! 202: NULL,
! 203: NULL,
! 204: NULL,
! 205: NULL,
! 206: "RES1",
! 207: "RES2",
! 208: "SRX",
! 209: "SR0",
! 210: "SR1",
! 211: "SR2",
! 212: "SR3",
! 213: NULL,
! 214: NULL,
! 215: NULL,
! 216: NULL,
! 217: "ICMD",
! 218: "ICTL",
! 219: "ISAR",
! 220: "ISAP",
! 221: "IUAP",
! 222: "IIR",
! 223: "IBP",
! 224: "IPPU",
! 225: "IPPL",
! 226: "ISR",
! 227: "ILAR",
! 228: "IPAR",
! 229: NULL,
! 230: NULL,
! 231: NULL,
! 232: "DCMD",
! 233: "DCTL",
! 234: "DSAR",
! 235: "DSAP",
! 236: "DUAP",
! 237: "DIR",
! 238: "DBP",
! 239: "DPPU",
! 240: "DPPL",
! 241: "DSR",
! 242: "DLAR",
! 243: "DPAR",
! 244: },
! 245: { /* SFU1 = FPU */
! 246: "FPECR",
! 247: NULL, NULL, NULL, NULL, NULL,
! 248: NULL, NULL, NULL, NULL, NULL,
! 249: NULL, NULL, NULL, NULL, NULL,
! 250: NULL, NULL, NULL, NULL, NULL,
! 251: NULL, NULL, NULL, NULL, NULL,
! 252: NULL, NULL, NULL, NULL, NULL,
! 253: NULL, NULL, NULL, NULL, NULL,
! 254: NULL, NULL, NULL, NULL, NULL,
! 255: NULL, NULL, NULL, NULL, NULL,
! 256: NULL, NULL, NULL, NULL, NULL,
! 257: NULL, NULL, NULL, NULL, NULL,
! 258: NULL, NULL, NULL, NULL, NULL,
! 259: NULL,
! 260: "FPSR",
! 261: "FPCR"
! 262: }
! 263: };
! 264:
! 265: /* print a comparison code */ /* XXX favors cmp vs fcmp or pcmp */
! 266: void
! 267: printcmp(int cpu, u_int code)
! 268: {
! 269: const char *cmp;
! 270:
! 271: if (cpu == CPU_88100 && code > 11)
! 272: cmp = NULL;
! 273: else
! 274: cmp = cmpname[code];
! 275: if (cmp != NULL)
! 276: db_printf("%s(%d)", cmp, code);
! 277: else
! 278: db_printf("%d", code);
! 279: }
! 280:
! 281: /* print a condition mnemnonic */
! 282: void
! 283: printcond(u_int match)
! 284: {
! 285: const char *cond;
! 286:
! 287: cond = condname[match];
! 288: if (cond != NULL)
! 289: db_printf("%s0", cond);
! 290: else
! 291: db_printf("%d", match);
! 292: }
! 293:
! 294: const char *
! 295: cregname(int cpu, u_int sfu, u_int regno)
! 296: {
! 297: static char regbuf[20];
! 298: const char *regname;
! 299:
! 300: switch (sfu) {
! 301: case 0: /* main unit */
! 302: case 1: /* SFU1 = FPU */
! 303: regname = cpu != CPU_88100 ?
! 304: m88110_ctrlreg[sfu][regno] : m88100_ctrlreg[sfu][regno];
! 305: if (regname == NULL)
! 306: snprintf(regbuf, sizeof regbuf,
! 307: sfu == 0 ? "cr%d" : "fcr%d", regno);
! 308: else
! 309: snprintf(regbuf, sizeof regbuf,
! 310: sfu == 0 ? "cr%d (%s)" : "fcr%d (%s)",
! 311: regno, regname);
! 312: break;
! 313: default: /* can't happen */
! 314: snprintf(regbuf, sizeof regbuf, "sfu%dcr%d", sfu, regno);
! 315: break;
! 316: }
! 317:
! 318: return (regbuf);
! 319: }
! 320:
! 321: void
! 322: symofset(u_int disp, u_int bit, vaddr_t iadr)
! 323: {
! 324: vaddr_t addr;
! 325:
! 326: if (disp & (1 << (bit - 1))) {
! 327: /* negative value */
! 328: addr = iadr + ((disp << 2) | (~0U << bit));
! 329: } else {
! 330: addr = iadr + (disp << 2);
! 331: }
! 332: db_printsym(addr, DB_STGY_PROC, db_printf);
! 333: }
! 334:
! 335: /* Handles immediate integer arithmetic instructions */
! 336: void
! 337: oimmed(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 338: {
! 339: int32_t Linst = inst & 0xffff;
! 340: u_int32_t H6inst = inst >> 26;
! 341: u_int32_t rs1 = (inst >> 16) & 0x1f;
! 342: u_int32_t rd = (inst >> 21) & 0x1f;
! 343:
! 344: switch (H6inst) {
! 345: case 0x11: /* and.u */
! 346: case 0x13: /* mask.u */
! 347: case 0x15: /* xor.u */
! 348: case 0x17: /* or.u */
! 349: db_printf("\t%s.u", opcode);
! 350: break;
! 351: default:
! 352: db_printf("\t%s ", opcode);
! 353: break;
! 354: }
! 355: db_printf("\t\tr%d, r%d, 0x%04x", rd, rs1, Linst);
! 356: }
! 357:
! 358: /* Handles instructions dealing with control registers */
! 359: void
! 360: ctrlregs(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 361: {
! 362: u_int32_t dir = (inst >> 14) & 0x03;
! 363: u_int32_t sfu = (inst >> 11) & 0x07;
! 364: u_int32_t creg = (inst >> 5) & 0x3f;
! 365: u_int32_t rd = (inst >> 21) & 0x1f;
! 366: u_int32_t rs1 = (inst >> 16) & 0x1f;
! 367:
! 368: db_printf("\t%s\t\t", opcode);
! 369:
! 370: switch (dir) {
! 371: case 0x01: /* ldcr, fldcr */
! 372: db_printf("r%d, %s", rd, cregname(cpu, sfu, creg));
! 373: break;
! 374: case 0x02: /* stcr, fstcr */
! 375: db_printf("r%d, %s", rs1, cregname(cpu, sfu, creg));
! 376: break;
! 377: default:
! 378: case 0x03: /* xcr, fxcr */
! 379: db_printf("r%d, r%d, %s",
! 380: rd, rs1, cregname(cpu, sfu, creg));
! 381: break;
! 382: }
! 383: }
! 384:
! 385: /* Handles floating point instructions */
! 386: void
! 387: sindou(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 388: {
! 389: u_int32_t rs2 = inst & 0x1f;
! 390: u_int32_t td = (inst >> 5) & 0x03;
! 391: u_int32_t t2 = (inst >> 7) & 0x03;
! 392: u_int32_t t1 = (inst >> 9) & 0x03;
! 393: u_int32_t rs1 = (inst >> 16) & 0x1f;
! 394: u_int32_t rd = (inst >> 21) & 0x1f;
! 395: u_int32_t checkbits = (inst >> 11) & 0x0f;
! 396: u_int32_t rf = (inst >> 15) & 0x01;
! 397:
! 398: /* do not display a specific fcmpu.s encoding as non-existing fcmpu.d */
! 399: if (checkbits == 0x07)
! 400: td = 0;
! 401:
! 402: /* do not display dot modifiers for mov.x */
! 403: if (checkbits == 0x08) {
! 404: db_printf("\t%s", opcode);
! 405: } else {
! 406: db_printf("\t%s.%c", opcode, sodname[td]);
! 407: }
! 408:
! 409: switch (checkbits) {
! 410: default:
! 411: case 0x00: /* fmul */
! 412: case 0x05: /* fadd */
! 413: case 0x06: /* fsub */
! 414: case 0x0e: /* fdiv */
! 415: db_printf("%c%c\t\t", sodname[t1], sodname[t2]);
! 416: if (rf != 0)
! 417: db_printf("x%d,x%d,x%d", rd, rs1, rs2);
! 418: else
! 419: db_printf("r%d,r%d,r%d", rd, rs1, rs2);
! 420: break;
! 421: case 0x01: /* fcvt */
! 422: case 0x0f: /* fsqrt */
! 423: db_printf("%c \t\t", sodname[t2]);
! 424: if (rf != 0)
! 425: db_printf("x%d, x%d", rd, rs2);
! 426: else
! 427: db_printf("r%d, r%d", rd, rs2);
! 428: break;
! 429: case 0x04: /* flt */
! 430: db_printf("%c \t\t", sodname[t2]);
! 431: if ((inst & 0x200) != 0) /* does not use the RF bit... */
! 432: db_printf("x%d, x%d", rd, rs2);
! 433: else
! 434: db_printf("r%d, r%d", rd, rs2);
! 435: break;
! 436: case 0x07: /* fcmp, fcmpu */
! 437: db_printf("%c%c\t\t", sodname[t1], sodname[t2]);
! 438: db_printf("r%d, ", rd);
! 439: if (rf != 0)
! 440: db_printf("x%d, x%d", rs1, rs2);
! 441: else
! 442: db_printf("r%d, r%d", rs1, rs2);
! 443: break;
! 444: case 0x08: /* mov */
! 445: if (rf != 0 && t1 == 0x01) { /* mov.x, displayed as mov */
! 446: db_printf(" \t\t");
! 447: db_printf("x%d, x%d", rd, rs2);
! 448: } else {
! 449: db_printf(".%c \t\t", sodname[t2]);
! 450:
! 451: if (t1 == 0)
! 452: db_printf("r%d, x%d", rd, rs2);
! 453: else
! 454: db_printf("x%d, r%d", rd, rs2);
! 455: }
! 456: break;
! 457: case 0x09: /* int */
! 458: case 0x0a: /* nint */
! 459: case 0x0b: /* trnc */
! 460: db_printf("%c \t\t", sodname[t2]);
! 461: if (rf != 0)
! 462: db_printf("r%d, x%d", rd, rs2);
! 463: else
! 464: db_printf("r%d, r%d", rd, rs2);
! 465: break;
! 466: }
! 467: }
! 468:
! 469: void
! 470: jump(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 471: {
! 472: u_int32_t rs2 = inst & 0x1f;
! 473:
! 474: db_printf("\t%s", opcode);
! 475: if ((inst & (1 << 10)) != 0)
! 476: db_printf(".n");
! 477: else
! 478: db_printf(" ");
! 479: db_printf("\t\tr%d", rs2);
! 480: }
! 481:
! 482: /* Handles ff1, ff0, tbnd and rte instructions */
! 483: void
! 484: instset(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 485: {
! 486: u_int32_t rs2 = inst & 0x1f;
! 487: u_int32_t rs1 = (inst >> 16) & 0x1f;
! 488: u_int32_t rd = (inst >> 21) & 0x1f;
! 489: u_int32_t checkbits = (inst >> 10) & 0x3f;
! 490: u_int32_t H6inst = (inst >> 26) & 0x3f;
! 491:
! 492: db_printf("\t%s", opcode);
! 493: if (H6inst == 0x3e) { /* tbnd with imm16 */
! 494: db_printf("\t\tr%d, 0x%04x", rs1, inst & 0xffff);
! 495: } else {
! 496: switch (checkbits) {
! 497: case 0x3a: /* ff1 */
! 498: case 0x3b: /* ff0 */
! 499: db_printf("\t\tr%d,r%d", rd, rs2);
! 500: break;
! 501: case 0x3e: /* tbnd */
! 502: db_printf("\t\tr%d,r%d", rs1, rs2);
! 503: break;
! 504: case 0x3f: /* rte, illop */
! 505: if (rs2 != 0)
! 506: db_printf("%d", rs2);
! 507: break;
! 508: }
! 509: }
! 510: }
! 511:
! 512: /* Handles unconditionnal branches */
! 513: void
! 514: obranch(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 515: {
! 516: u_int32_t disp = inst & 0x3ffffff;
! 517:
! 518: db_printf("\t%s", opcode);
! 519: if ((inst & (1 << 26)) != 0)
! 520: db_printf(".n");
! 521: else
! 522: db_printf(" ");
! 523: db_printf("\t\t");
! 524: symofset(disp, 26, iadr);
! 525: }
! 526:
! 527: /* Handles branch on conditions instructions */
! 528: void
! 529: brcond(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 530: {
! 531: u_int32_t match = (inst >> 21) & 0x1f;
! 532: u_int32_t rs = (inst >> 16) & 0x1f;
! 533: u_int32_t disp = inst & 0xffff;
! 534:
! 535: db_printf("\t%s", opcode);
! 536: if ((inst & (1 << 26)) != 0)
! 537: db_printf(".n");
! 538: else
! 539: db_printf(" ");
! 540: db_printf("\t\t");
! 541:
! 542: if (((inst >> 27) & 0x03) == 1) /* bcnd */
! 543: printcond(match);
! 544: else
! 545: printcmp(cpu, match);
! 546:
! 547: db_printf(", r%d, ", rs);
! 548: symofset(disp, 16, iadr);
! 549: }
! 550:
! 551: /* Handles trap instructions */
! 552: void
! 553: otrap(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 554: {
! 555: u_int32_t vecno = inst & 0x1ff;
! 556: u_int32_t match = (inst >> 21) & 0x1f;
! 557: u_int32_t rs = (inst >> 16) & 0x1f;
! 558:
! 559: db_printf("\t%s\t", opcode);
! 560: if (((inst >> 12) & 0x0f) == 0xe) /* tcnd */
! 561: printcond(match);
! 562: else
! 563: printcmp(cpu, match);
! 564: db_printf(", r%d, 0x%x", rs, vecno);
! 565: }
! 566:
! 567: /* Handles 10 bit immediate bit field operations */
! 568: void
! 569: obit(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 570: {
! 571: u_int32_t rs = (inst >> 16) & 0x1f;
! 572: u_int32_t rd = (inst >> 21) & 0x1f;
! 573: u_int32_t width = (inst >> 5) & 0x1f;
! 574: u_int32_t offset = inst & 0x1f;
! 575:
! 576: db_printf("\t%s\t\tr%d, r%d, ", opcode, rd, rs);
! 577: if (((inst >> 10) & 0x3f) != 0x2a) /* rot */
! 578: db_printf("%d", width);
! 579: db_printf("<%d>", offset);
! 580: }
! 581:
! 582: /* Handles triadic mode bit field instructions */
! 583: void
! 584: bitman(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 585: {
! 586: u_int32_t rs1 = (inst >> 16) & 0x1f;
! 587: u_int32_t rd = (inst >> 21) & 0x1f;
! 588: u_int32_t rs2 = inst & 0x1f;
! 589:
! 590: db_printf("\t%s\t\tr%d, r%d, r%d", opcode, rd, rs1, rs2);
! 591: }
! 592:
! 593: /* Handles immediate load/store/exchange instructions */
! 594: void
! 595: immem(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 596: {
! 597: u_int32_t rd = (inst >> 21) & 0x1f;
! 598: u_int32_t rs = (inst >> 16) & 0x1f;
! 599: u_int32_t st_lda = (inst >> 28) & 0x03;
! 600: u_int32_t aryno = (inst >> 26) & 0x03;
! 601: int rf = 0;
! 602: char c = ' ';
! 603:
! 604: switch (st_lda) {
! 605: case 0x00:
! 606: if ((aryno & 0x02) != 0) { /* 0x02, 0x03: ld.hu, ld.bu */
! 607: opcode = "ld";
! 608: c = 'u';
! 609: } else {
! 610: if (cpu == CPU_88100) {
! 611: opcode = "xmem";
! 612: if (aryno == 0) { /* xmem.bu */
! 613: aryno = 3;
! 614: c = 'u';
! 615: }
! 616: } else {
! 617: /* opcode = "ld"; */
! 618: rf = 1;
! 619: }
! 620: }
! 621: break;
! 622:
! 623: case 0x03:
! 624: if (cpu != CPU_88100) {
! 625: rf = 1;
! 626: switch (st_lda) {
! 627: case 0x00: /* ld.x */
! 628: aryno = 2;
! 629: break;
! 630: case 0x03: /* st, st.d, st.x */
! 631: break;
! 632: }
! 633: }
! 634: break;
! 635: }
! 636:
! 637: db_printf("\t%s%s%c\t\t", opcode,
! 638: rf != 0 ? xinstwidth[aryno] : instwidth[aryno], c);
! 639: if (rf != 0)
! 640: db_printf("x%d, r%d, ", rd, rs);
! 641: else
! 642: db_printf("r%d, r%d, ", rd, rs);
! 643: db_printf("0x%x", inst & 0xffff);
! 644: }
! 645:
! 646: /* Handles triadic mode load/store/exchange instructions */
! 647: void
! 648: nimmem(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 649: {
! 650: u_int32_t scaled = (inst >> 9) & 0x01;
! 651: u_int32_t rd = (inst >> 21) & 0x1f;
! 652: u_int32_t rs1 = (inst >> 16) & 0x1f;
! 653: u_int32_t rs2 = inst & 0x1f;
! 654: u_int32_t st_lda = (inst >> 12) & 0x03;
! 655: u_int32_t aryno = (inst >> 10) & 0x03;
! 656: char c = ' ';
! 657: int rf = 0, wt = 0, usr = 0;
! 658:
! 659: switch (st_lda) {
! 660: case 0x00:
! 661: switch (aryno) {
! 662: case 0x00: /* xmem.bu */
! 663: aryno = 3;
! 664: c = 'u';
! 665: /* FALLTHROUGH */
! 666: case 0x01: /* xmem */
! 667: opcode = "xmem";
! 668: break;
! 669: default:
! 670: case 0x02: /* ld.hu */
! 671: case 0x03: /* ld.bu */
! 672: opcode = "ld";
! 673: c = 'u';
! 674: break;
! 675: }
! 676: break;
! 677: case 0x01:
! 678: opcode = "ld";
! 679: if (cpu != CPU_88100) {
! 680: if ((inst & (1 << 26)) == 0)
! 681: rf = 1;
! 682: }
! 683: break;
! 684: case 0x02: /* st */
! 685: if (cpu != CPU_88100) {
! 686: if ((inst & (1 << 26)) == 0)
! 687: rf = 1;
! 688: if ((inst & (1 << 7)) != 0)
! 689: wt = 1;
! 690: }
! 691: break;
! 692: case 0x03:
! 693: if (cpu != CPU_88100) {
! 694: /* cheat instwidth for lda.x */
! 695: if (aryno == 3)
! 696: aryno = 4;
! 697: }
! 698: break;
! 699: }
! 700:
! 701: if (st_lda != 0x03 && (inst & (1 << 8)) != 0)
! 702: usr = 1;
! 703:
! 704: db_printf("\t%s%s%c%s%s\t",
! 705: opcode, rf != 0 ? xinstwidth[aryno] : instwidth[aryno], c,
! 706: usr != 0 ? ".usr" : " ", wt != 0 ? ".wt" : " ");
! 707: if (rf != 0)
! 708: db_printf("x%d, r%d", rd, rs1);
! 709: else
! 710: db_printf("r%d, r%d", rd, rs1);
! 711:
! 712: if (scaled != 0)
! 713: db_printf("[r%d]", rs2);
! 714: else
! 715: db_printf(", r%d", rs2);
! 716: }
! 717:
! 718: /* Handles triadic mode logical instructions */
! 719: void
! 720: lognim(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 721: {
! 722: u_int32_t rd = (inst >> 21) & 0x1f;
! 723: u_int32_t rs1 = (inst >> 16) & 0x1f;
! 724: u_int32_t rs2 = inst & 0x1f;
! 725:
! 726: db_printf("\t%s", opcode);
! 727: if ((inst & (1 << 10)) != 0)
! 728: db_printf(".c");
! 729:
! 730: db_printf("\t\tr%d, r%d, r%d", rd, rs1, rs2);
! 731: }
! 732:
! 733: /* Handles triadic mode arithmetic instructions */
! 734: void
! 735: onimmed(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 736: {
! 737: u_int32_t rd = (inst >> 21) & 0x1f;
! 738: u_int32_t rs1 = (inst >> 16) & 0x1f;
! 739: u_int32_t rs2 = inst & 0x1f;
! 740: u_int32_t carry = (inst >> 8) & 0x03;
! 741:
! 742: db_printf("\t%s", opcode);
! 743:
! 744: if ((inst & (1 << 11)) == 0) {
! 745: switch (carry) {
! 746: case 0x01:
! 747: db_printf(".co");
! 748: break;
! 749: case 0x02:
! 750: db_printf(".ci");
! 751: break;
! 752: case 0x03:
! 753: db_printf(".cio");
! 754: break;
! 755: }
! 756: } else {
! 757: if (cpu != CPU_88100 && carry == 0x01)
! 758: db_printf(".d");
! 759: }
! 760:
! 761: db_printf("\tr%d, r%d, r%d", rd, rs1, rs2);
! 762: }
! 763:
! 764: /* Handles 88110 SFU2 instructions */
! 765: void
! 766: pinst(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr)
! 767: {
! 768: u_int32_t rd = (inst >> 21) & 0x1f;
! 769: u_int32_t rs1 = (inst >> 16) & 0x1f;
! 770: u_int32_t rs2 = inst & 0x1f;
! 771: u_int32_t tfield = (inst >> 5) & 0x03;
! 772: u_int32_t pfunc = (inst >> 11) & 0x1f;
! 773: const char *saturation[] = { NULL, ".u", ".us", ".s" };
! 774:
! 775: db_printf("\t%s", opcode);
! 776:
! 777: switch (pfunc) {
! 778: case 0x0c: /* ppack */
! 779: db_printf(".%d", (inst >> 5) & 0x3c);
! 780: break;
! 781: case 0x0e: /* prot */
! 782: break;
! 783: default: /* other instructions have an S field or zero */
! 784: {
! 785: u_int32_t sfield = (inst >> 7) & 0x03;
! 786:
! 787: if (sfield != 0)
! 788: db_printf("%s", saturation[sfield]);
! 789: }
! 790: break;
! 791: }
! 792:
! 793: if (tfield != 0 || pfunc == 0x0d /* punpk */) {
! 794: if (tfield != 3)
! 795: db_printf(".%c", "nbh"[tfield]);
! 796: }
! 797:
! 798: switch (pfunc) {
! 799: case 0x0d: /* punpk */
! 800: db_printf("\tr%d, r%d", rd, rs1);
! 801: break;
! 802: case 0x0e: /* prot with immediate */
! 803: db_printf("\tr%d, r%d, %d", rd, rs1, (inst >> 5) & 0x3f);
! 804: break;
! 805: default:
! 806: db_printf("\tr%d, r%d, r%d", rd, rs1, rs2);
! 807: break;
! 808: }
! 809: }
! 810:
! 811: static const struct opdesc {
! 812: u_int32_t mask, match;
! 813: void (*opfun)(int, u_int32_t, const char *, vaddr_t);
! 814: const char *opcode;
! 815: } opdecode_88100[] = {
! 816: /* ORDER IS IMPORTANT BELOW */
! 817: { 0xf0000000, 0x00000000, immem, NULL }, /* xmem/ld */
! 818: { 0xf0000000, 0x10000000, immem, "ld" },
! 819: { 0xf0000000, 0x20000000, immem, "st" },
! 820: { 0xf0000000, 0x30000000, immem, "lda" },
! 821:
! 822: { 0xf8000000, 0x40000000, oimmed, "and" },
! 823: { 0xf8000000, 0x48000000, oimmed, "mask" },
! 824: { 0xf8000000, 0x50000000, oimmed, "xor" },
! 825: { 0xf8000000, 0x58000000, oimmed, "or" },
! 826: { 0xfc000000, 0x60000000, oimmed, "addu" },
! 827: { 0xfc000000, 0x64000000, oimmed, "subu" },
! 828: { 0xfc000000, 0x68000000, oimmed, "divu" },
! 829: { 0xfc000000, 0x6c000000, oimmed, "mul" },
! 830: { 0xfc000000, 0x70000000, oimmed, "add" },
! 831: { 0xfc000000, 0x74000000, oimmed, "sub" },
! 832: { 0xfc000000, 0x78000000, oimmed, "div" },
! 833: { 0xfc000000, 0x7c000000, oimmed, "cmp" },
! 834:
! 835: { 0xfc00f800, 0x80004000, ctrlregs, "ldcr" },
! 836: { 0xfc00f800, 0x80004800, ctrlregs, "fldcr" },
! 837: { 0xfc00f800, 0x80008000, ctrlregs, "stcr" },
! 838: { 0xfc00f800, 0x80008800, ctrlregs, "fstcr" },
! 839: { 0xfc00f800, 0x8000c000, ctrlregs, "xcr" },
! 840: { 0xfc00f800, 0x8000c800, ctrlregs, "fxcr" },
! 841:
! 842: { 0xfc00f800, 0x84000000, sindou, "fmul" },
! 843: { 0xfc1fff80, 0x84002000, sindou, "flt" },
! 844: { 0xfc00f800, 0x84002800, sindou, "fadd" },
! 845: { 0xfc00f800, 0x84003000, sindou, "fsub" },
! 846: { 0xfc00f860, 0x84003800, sindou, "fcmp" },
! 847: { 0xfc1ffe60, 0x84004800, sindou, "int" },
! 848: { 0xfc1ffe60, 0x84005000, sindou, "nint" },
! 849: { 0xfc1ffe60, 0x84005800, sindou, "trnc" },
! 850: { 0xfc00f800, 0x84007000, sindou, "fdiv" },
! 851:
! 852: { 0xf8000000, 0xc0000000, obranch, "br" },
! 853: { 0xf8000000, 0xc8000000, obranch, "bsr" },
! 854:
! 855: { 0xf8000000, 0xd0000000, brcond, "bb0" },
! 856: { 0xf8000000, 0xd8000000, brcond, "bb1" },
! 857: { 0xf8000000, 0xe8000000, brcond, "bcnd" },
! 858:
! 859: { 0xfc00fc00, 0xf0008000, obit, "clr" },
! 860: { 0xfc00fc00, 0xf0008800, obit, "set" },
! 861: { 0xfc00fc00, 0xf0009000, obit, "ext" },
! 862: { 0xfc00fc00, 0xf0009800, obit, "extu" },
! 863: { 0xfc00fc00, 0xf000a000, obit, "mak" },
! 864: { 0xfc00fc00, 0xf000a800, obit, "rot" },
! 865:
! 866: { 0xfc00fe00, 0xf000d000, otrap, "tb0" },
! 867: { 0xfc00fe00, 0xf000d800, otrap, "tb1" },
! 868: { 0xfc00fe00, 0xf000e800, otrap, "tcnd" },
! 869:
! 870: { 0xfc00f0e0, 0xf4000000, nimmem, NULL }, /* xmem/ld */
! 871: { 0xfc00f0e0, 0xf4001000, nimmem, "ld" },
! 872: { 0xfc00f0e0, 0xf4002000, nimmem, "st" },
! 873: { 0xfc00f0e0, 0xf4003000, nimmem, "lda" },
! 874:
! 875: { 0xfc00fbe0, 0xf4004000, lognim, "and" },
! 876: { 0xfc00fbe0, 0xf4005000, lognim, "xor" },
! 877: { 0xfc00fbe0, 0xf4005800, lognim, "or" },
! 878:
! 879: { 0xfc00fce0, 0xf4006000, onimmed, "addu" },
! 880: { 0xfc00fce0, 0xf4006400, onimmed, "subu" },
! 881: { 0xfc00fce0, 0xf4006800, onimmed, "divu" },
! 882: { 0xfc00fce0, 0xf4006c00, onimmed, "mul" },
! 883: { 0xfc00fce0, 0xf4007000, onimmed, "add" },
! 884: { 0xfc00fce0, 0xf4007400, onimmed, "sub" },
! 885: { 0xfc00fce0, 0xf4007800, onimmed, "div" },
! 886: { 0xfc00fce0, 0xf4007c00, onimmed, "cmp" },
! 887:
! 888: { 0xfc00ffe0, 0xf4008000, bitman, "clr" },
! 889: { 0xfc00ffe0, 0xf4008800, bitman, "set" },
! 890: { 0xfc00ffe0, 0xf4009000, bitman, "ext" },
! 891: { 0xfc00ffe0, 0xf4009800, bitman, "extu" },
! 892: { 0xfc00ffe0, 0xf400a000, bitman, "mak" },
! 893: { 0xfc00ffe0, 0xf400a800, bitman, "rot" },
! 894:
! 895: { 0xfc00fbe0, 0xf400c000, jump, "jmp" },
! 896: { 0xfc00fbe0, 0xf400c800, jump, "jsr" },
! 897:
! 898: { 0xfc00ffe0, 0xf400e800, instset, "ff1" },
! 899: { 0xfc00ffe0, 0xf400ec00, instset, "ff0" },
! 900: { 0xfc00ffe0, 0xf400f800, instset, "tbnd" },
! 901: { 0xfc00ffe0, 0xf400fc00, instset, "rte" },
! 902: { 0xfc000000, 0xf8000000, instset, "tbnd" },
! 903: { 0, 0, NULL, NULL }
! 904: }, opdecode_88110[] = {
! 905: /* ORDER IS IMPORTANT BELOW */
! 906: { 0xe0000000, 0x00000000, immem, "ld" },
! 907: { 0xf0000000, 0x20000000, immem, "st" },
! 908: { 0xfc000000, 0x3c000000, immem, "ld" },
! 909: { 0xf0000000, 0x30000000, immem, "st" },
! 910:
! 911: { 0xf8000000, 0x40000000, oimmed, "and" },
! 912: { 0xf8000000, 0x48000000, oimmed, "mask" },
! 913: { 0xf8000000, 0x50000000, oimmed, "xor" },
! 914: { 0xf8000000, 0x58000000, oimmed, "or" },
! 915: { 0xfc000000, 0x60000000, oimmed, "addu" },
! 916: { 0xfc000000, 0x64000000, oimmed, "subu" },
! 917: { 0xfc000000, 0x68000000, oimmed, "divu" },
! 918: { 0xfc000000, 0x6c000000, oimmed, "mulu" },
! 919: { 0xfc000000, 0x70000000, oimmed, "add" },
! 920: { 0xfc000000, 0x74000000, oimmed, "sub" },
! 921: { 0xfc000000, 0x78000000, oimmed, "divs" },
! 922: { 0xfc000000, 0x7c000000, oimmed, "cmp" },
! 923:
! 924: { 0xfc1ff81f, 0x80004000, ctrlregs, "ldcr" },
! 925: { 0xfc1ff81f, 0x80004800, ctrlregs, "fldcr" },
! 926: { 0xffe0f800, 0x80008000, ctrlregs, "stcr" },
! 927: { 0xffe0f800, 0x80008800, ctrlregs, "fstcr" },
! 928: { 0xfc00f800, 0x8000c000, ctrlregs, "xcr" },
! 929: { 0xfc00f800, 0x8000c800, ctrlregs, "fxcr" },
! 930:
! 931: { 0xfc007800, 0x84000000, sindou, "fmul" },
! 932: { 0xfc1f7e00, 0x84000800, sindou, "fcvt" },
! 933: { 0xfc1ffd80, 0x84002000, sindou, "flt" },
! 934: { 0xfc007800, 0x84002800, sindou, "fadd" },
! 935: { 0xfc007800, 0x84003000, sindou, "fsub" },
! 936: { 0xfc007860, 0x84003800, sindou, "fcmp" },
! 937: { 0xfc007860, 0x84003820, sindou, "fcmpu" },
! 938: { 0xfc1ffe60, 0x8400c000, sindou, "mov" },
! 939: { 0xfc17fe60, 0x84004200, sindou, "mov" },
! 940: { 0xfc1f7e60, 0x84004800, sindou, "int" },
! 941: { 0xfc1f7e60, 0x84005000, sindou, "nint" },
! 942: { 0xfc1f7e60, 0x84005800, sindou, "trnc" },
! 943: { 0xfc007800, 0x84007000, sindou, "fdiv" },
! 944: { 0xfc1f7e00, 0x84007800, sindou, "fsqrt" },
! 945:
! 946: { 0xfc00ffe0, 0x88000000, pinst, "pmul" },
! 947: { 0xfc00ff80, 0x88002000, pinst, "padd" },
! 948: { 0xfc00fe00, 0x88002000, pinst, "padds" },
! 949: { 0xfc00ff80, 0x88003000, pinst, "psub" },
! 950: { 0xfc00fe00, 0x88003000, pinst, "psubs" },
! 951: { 0xfc00ffe0, 0x88003860, pinst, "pcmp" },
! 952: { 0xfc00f800, 0x88006000, pinst, "ppack" },
! 953: { 0xfc00ff9f, 0x88006800, pinst, "punpk" },
! 954: { 0xfc00f87f, 0x88007000, pinst, "prot" },
! 955: { 0xfc00ffe0, 0x88007800, pinst, "prot" },
! 956:
! 957: { 0xf8000000, 0xc0000000, obranch, "br" },
! 958: { 0xf8000000, 0xc8000000, obranch, "bsr" },
! 959:
! 960: { 0xf8000000, 0xd0000000, brcond, "bb0" },
! 961: { 0xf8000000, 0xd8000000, brcond, "bb1" },
! 962: { 0xf8000000, 0xe8000000, brcond, "bcnd" },
! 963:
! 964: { 0xfc00fc00, 0xf0008000, obit, "clr" },
! 965: { 0xfc00fc00, 0xf0008800, obit, "set" },
! 966: { 0xfc00fc00, 0xf0009000, obit, "ext" },
! 967: { 0xfc00fc00, 0xf0009800, obit, "extu" },
! 968: { 0xfc00fc00, 0xf000a000, obit, "mak" },
! 969: { 0xfc00ffe0, 0xf000a800, obit, "rot" },
! 970:
! 971: { 0xfc00fe00, 0xf000d000, otrap, "tb0" },
! 972: { 0xfc00fe00, 0xf000d800, otrap, "tb1" },
! 973: { 0xfc00fe00, 0xf000e800, otrap, "tcnd" },
! 974:
! 975: { 0xfc00f0e0, 0xf4000000, nimmem, NULL }, /* ld/xmem */
! 976: { 0xf800f0e0, 0xf0001000, nimmem, "ld" },
! 977: { 0xf800f060, 0xf0002000, nimmem, "st" },
! 978: { 0xfc00f2e0, 0xf4003200, nimmem, "lda" },
! 979:
! 980: { 0xfc00fbe0, 0xf4004000, lognim, "and" },
! 981: { 0xfc00fbe0, 0xf4005000, lognim, "xor" },
! 982: { 0xfc00fbe0, 0xf4005800, lognim, "or" },
! 983:
! 984: { 0xfc00fce0, 0xf4006000, onimmed, "addu" },
! 985: { 0xfc00fce0, 0xf4006400, onimmed, "subu" },
! 986: { 0xfc00fee0, 0xf4006800, onimmed, "divu" },
! 987: { 0xfc00fee0, 0xf4006c00, onimmed, "mulu" },
! 988: { 0xfc00ffe0, 0xf4006e00, onimmed, "muls" },
! 989: { 0xfc00fce0, 0xf4007000, onimmed, "add" },
! 990: { 0xfc00fce0, 0xf4007400, onimmed, "sub" },
! 991: { 0xfc00ffe0, 0xf4007800, onimmed, "divs" },
! 992: { 0xfc00ffe0, 0xf4007c00, onimmed, "cmp" },
! 993:
! 994: { 0xfc00ffe0, 0xf4008000, bitman, "clr" },
! 995: { 0xfc00ffe0, 0xf4008800, bitman, "set" },
! 996: { 0xfc00ffe0, 0xf4009000, bitman, "ext" },
! 997: { 0xfc00ffe0, 0xf4009800, bitman, "extu" },
! 998: { 0xfc00ffe0, 0xf400a000, bitman, "mak" },
! 999: { 0xfc00ffe0, 0xf400a800, bitman, "rot" },
! 1000:
! 1001: { 0xfffffbe0, 0xf400c000, jump, "jmp" },
! 1002: { 0xfffffbe0, 0xf400c800, jump, "jsr" },
! 1003:
! 1004: { 0xfc1fffe0, 0xf400e800, instset, "ff1" },
! 1005: { 0xfc1fffe0, 0xf400ec00, instset, "ff0" },
! 1006: { 0xffe0ffe0, 0xf400f800, instset, "tbnd" },
! 1007: { 0xffffffff, 0xf400fc00, instset, "rte" },
! 1008: { 0xfffffffc, 0xf400fc00, instset, "illop" },
! 1009: { 0xffe00000, 0xf8000000, instset, "tbnd" },
! 1010: { 0, 0, NULL, NULL }
! 1011: };
! 1012:
! 1013: void
! 1014: m88k_print_instruction(int cpu, u_int iadr, u_int32_t inst)
! 1015: {
! 1016: const struct opdesc *p;
! 1017:
! 1018: /*
! 1019: * This messes up "or.b" instructions ever so slightly,
! 1020: * but keeps us in sync between routines...
! 1021: */
! 1022: if (inst == 0) {
! 1023: db_printf("\t.word\t0\n");
! 1024: } else {
! 1025: p = cpu != CPU_88100 ? opdecode_88110 : opdecode_88100;
! 1026: while (p->mask != 0) {
! 1027: if ((inst & p->mask) == p->match) {
! 1028: (*p->opfun)(cpu, inst, p->opcode, iadr);
! 1029: db_printf("\n");
! 1030: return;
! 1031: }
! 1032: p++;
! 1033: }
! 1034: db_printf("\t.word\t0x%x\n", inst);
! 1035: }
! 1036: }
! 1037:
! 1038: db_addr_t
! 1039: db_disasm(db_addr_t loc, boolean_t altfmt)
! 1040: {
! 1041: int cpu;
! 1042:
! 1043: if (altfmt)
! 1044: cpu = CPU_IS88100 ? CPU_88110 : CPU_88100;
! 1045: else
! 1046: cpu = cputyp;
! 1047:
! 1048: m88k_print_instruction(cpu, loc, db_get_value(loc, 4, FALSE));
! 1049: return (loc + 4);
! 1050: }
CVSweb