|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)opset.c 4.8 (Berkeley) 1/16/89"; ! 3: #endif ! 4: ! 5: /* ! 6: * adb - instruction printing routines: VAX version ! 7: */ ! 8: ! 9: #include "defs.h" ! 10: ! 11: /* ! 12: * Get assembler definitions; declare tables that appear in optab.c. ! 13: */ ! 14: #define ADB ! 15: #undef INSTTAB ! 16: #include "instrs.h" ! 17: ! 18: extern struct insttab insttab[]; ! 19: extern char *regname[]; ! 20: extern char *fltimm[]; ! 21: ! 22: /* these are shared with the assembler: */ ! 23: extern int ty_NORELOC[]; ! 24: extern int ty_nbyte[]; ! 25: #ifdef notyet ! 26: extern int ty_float[]; /* must update assizetab.c */ ! 27: #endif ! 28: ! 29: /* ! 30: * Definitions for registers and for operand classes. ! 31: */ ! 32: #define R_PC 0xF ! 33: ! 34: #define OC_IMM0 0x0 /* literal, aka immediate */ ! 35: #define OC_IMM1 0x1 ! 36: #define OC_IMM2 0x2 ! 37: #define OC_IMM3 0x3 ! 38: #define OC_INDEX 0x4 /* [rN] */ ! 39: #define OC_REG 0x5 /* rN */ ! 40: #define OC_DREG 0x6 /* (rN) */ ! 41: #define OC_ADREG 0x7 /* -(rN) */ ! 42: #define OC_AIREG 0x8 /* (rN)+ */ ! 43: #define OC_DAIREG 0x9 /* *(rN)+ */ ! 44: #define OC_BDISP 0xA /* b(rN) */ ! 45: #define OC_DBDISP 0xB /* *b(rN) */ ! 46: #define OC_WDISP 0xC /* w(rN) */ ! 47: #define OC_DWDISP 0xD /* *w(rN) */ ! 48: #define OC_LDISP 0xE /* l(rN) */ ! 49: #define OC_DLDISP 0xF /* *l(rN) */ ! 50: ! 51: #define OC_SHIFT 4 ! 52: #define OC_CONS(oc,reg) (((oc & 0xF) << OC_SHIFT) | (reg & 0xF)) ! 53: #define OC_AMEXT(x) (((x) >> OC_SHIFT) & 0xF) ! 54: #define OC_REGEXT(x) ((x) & 0xF) ! 55: ! 56: /* ! 57: * Definitions for special instructions. ! 58: */ ! 59: #define CASEB 0x8F ! 60: #define CASEW 0xAF ! 61: #define CASEL 0xCF ! 62: #define CHMK 0xBC ! 63: ! 64: /* ! 65: * ioptab is a two level 1-based index by opcode into insttab. ! 66: * The first level into ioptab is given by mapescbyte(). ! 67: * Since ioptab is 1-based, references would be expected to ! 68: * be of the form ! 69: * ! 70: * ptr = &insttab[ioptab[a][b] - 1]; ! 71: * ! 72: * but the form ! 73: * ! 74: * ptr = &(insttab - 1)[ioptab[a][b]] ! 75: * ! 76: * is equivalent and generates less code (!) (time to work on the ! 77: * compiler again...). ! 78: */ ! 79: static short ioptab[3][256]; ! 80: #define mapescbyte(b) ((b) == ESCD ? 1 : (b) == ESCF ? 2 : 0) ! 81: ! 82: mkioptab() ! 83: { ! 84: register struct insttab *p; ! 85: register int mapchar; ! 86: register short *iop; ! 87: ! 88: /* ! 89: * The idea here is that whenever two opcodes have the same ! 90: * codes, but different mnemonics, we want to prefer the one ! 91: * with the `simpler' type. Here lower numbers make simpler ! 92: * types. This seems (likely) to work reasonably well. ! 93: * ! 94: * At present, this affects the following opcodes: ! 95: * ! 96: * 7c clrq | clrd | clrg ! 97: * 7e movaq | movad | movag ! 98: * 7f pushaq | pushad | pushag ! 99: * d4 clrl | clrf ! 100: * de moval | movaf ! 101: * df pushal | pushaf ! 102: * ! 103: * In each case, the leftmost mnemonics are preferred. ! 104: */ ! 105: #define PREFER(a, b) (A_TYPEXT((a)->argtype[0]) < A_TYPEXT((b)->argtype[0])) ! 106: ! 107: for (p = insttab; p->iname != NULL; p++) { ! 108: mapchar = mapescbyte(p->eopcode); ! 109: iop = &ioptab[mapchar][p->popcode]; ! 110: if (*iop == 0 || PREFER(p, &(insttab - 1)[*iop])) ! 111: *iop = p - (insttab - 1); ! 112: } ! 113: #undef PREFER ! 114: } ! 115: ! 116: /* ! 117: * Global variables for communication between the minions and printins. ! 118: */ ! 119: static int idsp; /* which space we are in (INSTR or DATA) */ ! 120: static int argno; /* which argument we are working on */ ! 121: static int dotoff; /* offset from dot for this arg */ ! 122: static int vset[7]; /* set by savevar, cleared by clrvar */ ! 123: ! 124: #define savevar(v) (vset[argno] = 1, var[argno] = v) ! 125: #define clrvar(v) (vset[argno] = 0, var[argno] = 0x80000000) ! 126: ! 127: /* ! 128: * Read some bytes, checking for errors, and updating the offset. ! 129: */ ! 130: #define getsomebytes(ptr, nbytes) \ ! 131: (void) adbread(idsp, inkdot(dotoff), ptr, nbytes); \ ! 132: checkerr(); \ ! 133: dotoff += (nbytes) ! 134: ! 135: /* ! 136: * Read one byte, and advance the offset. ! 137: */ ! 138: static int ! 139: getbyte() ! 140: { ! 141: u_char c; ! 142: ! 143: getsomebytes(&c, sizeof(c)); ! 144: return (c); ! 145: } ! 146: ! 147: /* ! 148: * adb's view: printins() prints one instruction, and sets dotinc. ! 149: */ ! 150: printins(space) ! 151: int space; ! 152: { ! 153: register u_char *ap; ! 154: register struct insttab *ip; ! 155: int ins, mode, optype, mapchar, t; ! 156: char *lastix, *ixreg; ! 157: char *operandout(); ! 158: ! 159: /* ! 160: * Set up the module variables, pick up the instruction, and ! 161: * find its table entry. ! 162: */ ! 163: idsp = space; ! 164: dotoff = 0; ! 165: ins = idsp == SP_NONE ? (u_char)dot : getbyte(); ! 166: if ((mapchar = mapescbyte(ins)) != 0) { ! 167: t = getbyte(); ! 168: if (ioptab[mapchar][t] == 0) { ! 169: /* ! 170: * Oops; not a defined instruction; back over this ! 171: * escape byte. ! 172: */ ! 173: dotoff--; ! 174: mapchar = 0; ! 175: } else ! 176: ins = t; ! 177: } ! 178: if ((t = ioptab[mapchar][ins]) == 0) { ! 179: adbprintf("<undefined operator byte>: %x", ins); ! 180: dotinc = 1; ! 181: return; ! 182: } ! 183: ip = &(insttab - 1)[t]; ! 184: adbprintf("%s%8t", ip->iname); ! 185: ! 186: /* ! 187: * For each argument, decode that argument. ! 188: * We set t if we notice something fishy. ! 189: */ ! 190: t = 0; ! 191: for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++) { ! 192: optype = *ap++; ! 193: clrvar(); ! 194: if (argno != 0) ! 195: printc(','); ! 196: /* ! 197: * lastix and ixreg track the register indexed addressing ! 198: * mode, which is written as <stuff>[reg] but encoded as ! 199: * [reg]<stuff>. Only one [reg] is legal. ! 200: */ ! 201: lastix = NULL; ! 202: do { ! 203: /* check for special pc-relative (branch) */ ! 204: if (A_ACCEXT(optype) & ACCB) { ! 205: switch (A_TYPEXT(optype)) { ! 206: case TYPB: ! 207: mode = OC_CONS(OC_BDISP, R_PC); ! 208: break; ! 209: case TYPW: ! 210: mode = OC_CONS(OC_WDISP, R_PC); ! 211: break; ! 212: } ! 213: } else ! 214: mode = getbyte(); ! 215: ixreg = operandout(mode, optype, ins == CHMK); ! 216: if (lastix) { ! 217: adbprintf("[%s]", lastix); ! 218: if (ixreg) ! 219: t = 1; ! 220: } ! 221: } while ((lastix = ixreg) != NULL); ! 222: } ! 223: if (t) ! 224: adbprintf("%4t# not code? illegal arguments detected "); ! 225: switch (ins) { ! 226: case CASEB: ! 227: case CASEW: ! 228: case CASEL: ! 229: if (mapchar == 0 && vset[1] && vset[2]) ! 230: casebody(var[1], var[2]); ! 231: else ! 232: adbprintf("\n%4t# not code? non-constant cases "); ! 233: } ! 234: dotinc = dotoff; ! 235: } ! 236: ! 237: /* ! 238: * Print out the locations to which each of the cases branch. ! 239: * This routine carefully allows expressions such as ! 240: * ! 241: * casel <val>,$<const>,$0x7fffffff ! 242: * ! 243: * even though they do not fit on a VAX. ! 244: */ ! 245: static ! 246: casebody(base, limit) ! 247: register expr_t base, limit; ! 248: { ! 249: register expr_t i = -1; ! 250: register addr_t a, baseaddr = inkdot(dotoff); ! 251: short displ; ! 252: ! 253: argno = 0; ! 254: do { ! 255: i++; ! 256: adbprintf("\n %R: ", base++); ! 257: getsomebytes(&displ, sizeof(displ)); ! 258: a = displ + baseaddr; ! 259: psymoff("%R", a, SP_DATA, maxoff, ""); ! 260: savevar(a); ! 261: } while (i != limit); ! 262: } ! 263: ! 264: /* ! 265: * Handle a normal operand. Return pointer to register ! 266: * name if this is an index instruction, else return NULL. ! 267: */ ! 268: static char * ! 269: operandout(mode, optype, ischmk) ! 270: register int mode; ! 271: int optype, ischmk; ! 272: { ! 273: register char *r; ! 274: register int regnumber, nbytes, n; ! 275: union { ! 276: char b; ! 277: short w; ! 278: int l; ! 279: } displ; ! 280: extern char *syscalls[]; ! 281: extern int nsys; ! 282: ! 283: regnumber = OC_REGEXT(mode); ! 284: r = regname[regnumber]; ! 285: switch (OC_AMEXT(mode)) { ! 286: ! 287: case OC_IMM0: case OC_IMM1: ! 288: case OC_IMM2: case OC_IMM3: ! 289: savevar(mode); ! 290: printc('$'); ! 291: #ifdef notyet ! 292: if (ty_float[A_TYPEXT(optype)]) ! 293: prints(fltimm[mode]); ! 294: else if (ischmk && (u_int)mode < nsys && syscalls[mode]) ! 295: prints(syscalls[mode]); ! 296: else ! 297: adbprintf("%V", mode); ! 298: #else ! 299: switch (A_TYPEXT(optype)) { ! 300: ! 301: case TYPF: ! 302: case TYPD: ! 303: case TYPG: ! 304: case TYPH: ! 305: prints(fltimm[mode]); ! 306: break; ! 307: ! 308: default: ! 309: if (ischmk && (u_int)mode < nsys && syscalls[mode]) ! 310: prints(syscalls[mode]); ! 311: else ! 312: adbprintf("%V", mode); ! 313: break; ! 314: } ! 315: #endif ! 316: return (0); ! 317: ! 318: case OC_INDEX: ! 319: return (r); /* will be printed later */ ! 320: ! 321: case OC_REG: ! 322: adbprintf("%s", r); ! 323: return (0); ! 324: ! 325: case OC_DREG: ! 326: adbprintf("(%s)", r); ! 327: return (0); ! 328: ! 329: case OC_ADREG: ! 330: adbprintf("-(%s)", r); ! 331: return (0); ! 332: ! 333: case OC_DAIREG: ! 334: printc('*'); ! 335: /* FALLTHROUGH */ ! 336: ! 337: case OC_AIREG: ! 338: if (regnumber != R_PC) { ! 339: adbprintf("(%s)+", r); ! 340: return (0); ! 341: } ! 342: /* PC immediate */ ! 343: printc('$'); ! 344: if (mode == OC_CONS(OC_DAIREG, R_PC)) ! 345: /* PC absolute, always 4 bytes */ ! 346: nbytes = 4; ! 347: else { ! 348: nbytes = ty_nbyte[A_TYPEXT(optype)]; ! 349: if (ty_NORELOC[A_TYPEXT(optype)]) { ! 350: bignumprint(nbytes, optype); ! 351: return (0); ! 352: } ! 353: } ! 354: break; ! 355: ! 356: case OC_DBDISP: ! 357: printc('*'); ! 358: /* FALLTHROUGH */ ! 359: ! 360: case OC_BDISP: ! 361: nbytes = 1; ! 362: break; ! 363: ! 364: case OC_DWDISP: ! 365: printc('*'); ! 366: /* FALLTHROUGH */ ! 367: ! 368: case OC_WDISP: ! 369: nbytes = 2; ! 370: break; ! 371: ! 372: case OC_DLDISP: ! 373: printc('*'); ! 374: /* FALLTHROUGH */ ! 375: ! 376: case OC_LDISP: ! 377: nbytes = 4; ! 378: break; ! 379: ! 380: default: ! 381: panic("operandout 1"); ! 382: /* NOTREACHED */ ! 383: } ! 384: ! 385: /* ! 386: * Print a displacement format. ! 387: */ ! 388: getsomebytes(&displ, nbytes); ! 389: switch (nbytes) { ! 390: case 1: ! 391: n = displ.b; ! 392: break; ! 393: case 2: ! 394: n = displ.w; ! 395: break; ! 396: case 4: ! 397: n = displ.l; ! 398: break; ! 399: default: ! 400: panic("operandout 2"); ! 401: /* NOTREACHED */ ! 402: } ! 403: if (regnumber == R_PC) { ! 404: switch (OC_AMEXT(mode)) { ! 405: ! 406: case OC_DAIREG: ! 407: if (ischmk && (u_int)n < nsys && syscalls[n]) { ! 408: prints(syscalls[n]); ! 409: return (0); ! 410: } ! 411: break; ! 412: ! 413: case OC_BDISP: case OC_DBDISP: ! 414: case OC_WDISP: case OC_DWDISP: ! 415: case OC_LDISP: case OC_DLDISP: ! 416: /* PC offset */ ! 417: n += dot + dotoff; ! 418: } ! 419: psymoff("%V", (addr_t)n, SP_DATA, maxoff, ""); ! 420: } else ! 421: adbprintf("%V(%s)", (expr_t)n, regname[regnumber]); ! 422: savevar(n); ! 423: return (0); ! 424: } ! 425: ! 426: /* ! 427: * Print an F-float, D-float, G-float, H-float, quadword, or octaword. ! 428: * F- and D-floating values are printed as themselves, unless they are ! 429: * reserved operand bit patterns; these, and the others, are printed ! 430: * instead in hex, with leading zeroes suppressed. ! 431: */ ! 432: static ! 433: bignumprint(nbytes, optype) ! 434: int nbytes, optype; ! 435: { ! 436: register char *p; ! 437: register int i; ! 438: union { ! 439: float f; /* if f-floating */ ! 440: double d; /* if d-floating */ ! 441: u_char c[16]; /* if G, H, Q, or O */ ! 442: } n; ! 443: char expbuf[4*8+1]; /* max 4 8-character hex ints */ ! 444: static char tohex[] = "0123456789abcdef"; ! 445: ! 446: /* ! 447: * Read in the number, then figure out how to print it. ! 448: */ ! 449: getsomebytes(&n, nbytes); ! 450: switch (A_TYPEXT(optype)) { ! 451: ! 452: case TYPF: ! 453: if ((p = checkfloat((caddr_t)&n.f, 0)) == NULL) { ! 454: adbprintf("0f%f", n.f); ! 455: return; ! 456: } ! 457: adbprintf("%s 0f::", p); ! 458: break; ! 459: ! 460: case TYPD: ! 461: if ((p = checkfloat((caddr_t)&n.d, 1)) == NULL) { ! 462: adbprintf("0d%f", n.d); ! 463: return; ! 464: } ! 465: adbprintf("%s 0d::", p); ! 466: break; ! 467: ! 468: case TYPG: ! 469: adbprintf("0g::"); ! 470: break; ! 471: ! 472: case TYPH: ! 473: adbprintf("0h::"); ! 474: break; ! 475: ! 476: case TYPQ: ! 477: case TYPO: ! 478: break; ! 479: ! 480: default: ! 481: panic("bignumprint"); ! 482: } ! 483: ! 484: /* ! 485: * Expand the number into expbuf, then skip leading zeroes. ! 486: * Be careful not to skip the entire number. ! 487: */ ! 488: for (p = expbuf, i = nbytes; --i >= 0;) { ! 489: *p++ = tohex[n.c[i] >> 4]; ! 490: *p++ = tohex[n.c[i] & 15]; ! 491: } ! 492: for (p = expbuf; *p == '0'; p++) ! 493: /* void */; ! 494: prints(*p ? p : p - 1); ! 495: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.