1 #ifndef lint 2 static char sccsid[] = "@(#)opset.c 4.8 (Berkeley) 01/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 } 496