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