18912Srrh #ifndef lint 2*36564Sbostic static char sccsid[] = "@(#)opset.c 4.8 (Berkeley) 01/16/89"; 3*36564Sbostic #endif 4*36564Sbostic 53760Sroot /* 6*36564Sbostic * adb - instruction printing routines: VAX version 73760Sroot */ 83760Sroot 93760Sroot #include "defs.h" 103760Sroot 11*36564Sbostic /* 12*36564Sbostic * Get assembler definitions; declare tables that appear in optab.c. 13*36564Sbostic */ 14*36564Sbostic #define ADB 158912Srrh #undef INSTTAB 168912Srrh #include "instrs.h" 173760Sroot 18*36564Sbostic extern struct insttab insttab[]; 19*36564Sbostic extern char *regname[]; 20*36564Sbostic extern char *fltimm[]; 21*36564Sbostic 22*36564Sbostic /* these are shared with the assembler: */ 23*36564Sbostic extern int ty_NORELOC[]; 24*36564Sbostic extern int ty_nbyte[]; 25*36564Sbostic #ifdef notyet 26*36564Sbostic extern int ty_float[]; /* must update assizetab.c */ 27*36564Sbostic #endif 28*36564Sbostic 293760Sroot /* 30*36564Sbostic * Definitions for registers and for operand classes. 313760Sroot */ 328912Srrh #define R_PC 0xF 338912Srrh 34*36564Sbostic #define OC_IMM0 0x0 /* literal, aka immediate */ 358912Srrh #define OC_IMM1 0x1 368912Srrh #define OC_IMM2 0x2 378912Srrh #define OC_IMM3 0x3 38*36564Sbostic #define OC_INDEX 0x4 /* [rN] */ 39*36564Sbostic #define OC_REG 0x5 /* rN */ 40*36564Sbostic #define OC_DREG 0x6 /* (rN) */ 41*36564Sbostic #define OC_ADREG 0x7 /* -(rN) */ 42*36564Sbostic #define OC_AIREG 0x8 /* (rN)+ */ 43*36564Sbostic #define OC_DAIREG 0x9 /* *(rN)+ */ 44*36564Sbostic #define OC_BDISP 0xA /* b(rN) */ 45*36564Sbostic #define OC_DBDISP 0xB /* *b(rN) */ 46*36564Sbostic #define OC_WDISP 0xC /* w(rN) */ 47*36564Sbostic #define OC_DWDISP 0xD /* *w(rN) */ 48*36564Sbostic #define OC_LDISP 0xE /* l(rN) */ 49*36564Sbostic #define OC_DLDISP 0xF /* *l(rN) */ 508912Srrh 518912Srrh #define OC_SHIFT 4 528912Srrh #define OC_CONS(oc,reg) (((oc & 0xF) << OC_SHIFT) | (reg & 0xF)) 538912Srrh #define OC_AMEXT(x) (((x) >> OC_SHIFT) & 0xF) 548912Srrh #define OC_REGEXT(x) ((x) & 0xF) 558912Srrh 563760Sroot /* 57*36564Sbostic * Definitions for special instructions. 583760Sroot */ 598912Srrh #define CASEB 0x8F 608912Srrh #define CASEW 0xAF 618912Srrh #define CASEL 0xCF 62*36564Sbostic #define CHMK 0xBC 63*36564Sbostic 648912Srrh /* 65*36564Sbostic * ioptab is a two level 1-based index by opcode into insttab. 66*36564Sbostic * The first level into ioptab is given by mapescbyte(). 67*36564Sbostic * Since ioptab is 1-based, references would be expected to 68*36564Sbostic * be of the form 69*36564Sbostic * 70*36564Sbostic * ptr = &insttab[ioptab[a][b] - 1]; 71*36564Sbostic * 72*36564Sbostic * but the form 73*36564Sbostic * 74*36564Sbostic * ptr = &(insttab - 1)[ioptab[a][b]] 75*36564Sbostic * 76*36564Sbostic * is equivalent and generates less code (!) (time to work on the 77*36564Sbostic * compiler again...). 788912Srrh */ 79*36564Sbostic static short ioptab[3][256]; 80*36564Sbostic #define mapescbyte(b) ((b) == ESCD ? 1 : (b) == ESCF ? 2 : 0) 813760Sroot 828912Srrh mkioptab() 838912Srrh { 84*36564Sbostic register struct insttab *p; 85*36564Sbostic register int mapchar; 86*36564Sbostic register short *iop; 873760Sroot 88*36564Sbostic /* 89*36564Sbostic * The idea here is that whenever two opcodes have the same 90*36564Sbostic * codes, but different mnemonics, we want to prefer the one 91*36564Sbostic * with the `simpler' type. Here lower numbers make simpler 92*36564Sbostic * types. This seems (likely) to work reasonably well. 93*36564Sbostic * 94*36564Sbostic * At present, this affects the following opcodes: 95*36564Sbostic * 96*36564Sbostic * 7c clrq | clrd | clrg 97*36564Sbostic * 7e movaq | movad | movag 98*36564Sbostic * 7f pushaq | pushad | pushag 99*36564Sbostic * d4 clrl | clrf 100*36564Sbostic * de moval | movaf 101*36564Sbostic * df pushal | pushaf 102*36564Sbostic * 103*36564Sbostic * In each case, the leftmost mnemonics are preferred. 104*36564Sbostic */ 105*36564Sbostic #define PREFER(a, b) (A_TYPEXT((a)->argtype[0]) < A_TYPEXT((b)->argtype[0])) 106*36564Sbostic 107*36564Sbostic for (p = insttab; p->iname != NULL; p++) { 1088912Srrh mapchar = mapescbyte(p->eopcode); 109*36564Sbostic iop = &ioptab[mapchar][p->popcode]; 110*36564Sbostic if (*iop == 0 || PREFER(p, &(insttab - 1)[*iop])) 111*36564Sbostic *iop = p - (insttab - 1); 1123760Sroot } 113*36564Sbostic #undef PREFER 1143760Sroot } 1153760Sroot 1168912Srrh /* 117*36564Sbostic * Global variables for communication between the minions and printins. 1188912Srrh */ 119*36564Sbostic static int idsp; /* which space we are in (INSTR or DATA) */ 120*36564Sbostic static int argno; /* which argument we are working on */ 121*36564Sbostic static int dotoff; /* offset from dot for this arg */ 122*36564Sbostic static int vset[7]; /* set by savevar, cleared by clrvar */ 1233760Sroot 124*36564Sbostic #define savevar(v) (vset[argno] = 1, var[argno] = v) 125*36564Sbostic #define clrvar(v) (vset[argno] = 0, var[argno] = 0x80000000) 126*36564Sbostic 127*36564Sbostic /* 128*36564Sbostic * Read some bytes, checking for errors, and updating the offset. 129*36564Sbostic */ 130*36564Sbostic #define getsomebytes(ptr, nbytes) \ 131*36564Sbostic (void) adbread(idsp, inkdot(dotoff), ptr, nbytes); \ 132*36564Sbostic checkerr(); \ 133*36564Sbostic dotoff += (nbytes) 134*36564Sbostic 135*36564Sbostic /* 136*36564Sbostic * Read one byte, and advance the offset. 137*36564Sbostic */ 138*36564Sbostic static int 139*36564Sbostic getbyte() 1408912Srrh { 141*36564Sbostic u_char c; 142*36564Sbostic 143*36564Sbostic getsomebytes(&c, sizeof(c)); 144*36564Sbostic return (c); 1458912Srrh } 1468912Srrh 147*36564Sbostic /* 148*36564Sbostic * adb's view: printins() prints one instruction, and sets dotinc. 149*36564Sbostic */ 150*36564Sbostic printins(space) 151*36564Sbostic int space; 1523760Sroot { 153*36564Sbostic register u_char *ap; 154*36564Sbostic register struct insttab *ip; 155*36564Sbostic int ins, mode, optype, mapchar, t; 156*36564Sbostic char *lastix, *ixreg; 157*36564Sbostic char *operandout(); 1583760Sroot 159*36564Sbostic /* 160*36564Sbostic * Set up the module variables, pick up the instruction, and 161*36564Sbostic * find its table entry. 162*36564Sbostic */ 163*36564Sbostic idsp = space; 164*36564Sbostic dotoff = 0; 165*36564Sbostic ins = idsp == SP_NONE ? (u_char)dot : getbyte(); 166*36564Sbostic if ((mapchar = mapescbyte(ins)) != 0) { 167*36564Sbostic t = getbyte(); 168*36564Sbostic if (ioptab[mapchar][t] == 0) { 1698912Srrh /* 170*36564Sbostic * Oops; not a defined instruction; back over this 171*36564Sbostic * escape byte. 1728912Srrh */ 173*36564Sbostic dotoff--; 1748912Srrh mapchar = 0; 175*36564Sbostic } else 176*36564Sbostic ins = t; 1778912Srrh } 178*36564Sbostic if ((t = ioptab[mapchar][ins]) == 0) { 179*36564Sbostic adbprintf("<undefined operator byte>: %x", ins); 180*36564Sbostic dotinc = 1; 181*36564Sbostic return; 1828912Srrh } 183*36564Sbostic ip = &(insttab - 1)[t]; 184*36564Sbostic adbprintf("%s%8t", ip->iname); 1858912Srrh 186*36564Sbostic /* 187*36564Sbostic * For each argument, decode that argument. 188*36564Sbostic * We set t if we notice something fishy. 189*36564Sbostic */ 190*36564Sbostic t = 0; 191*36564Sbostic for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++) { 192*36564Sbostic optype = *ap++; 193*36564Sbostic clrvar(); 1948912Srrh if (argno != 0) 1958912Srrh printc(','); 196*36564Sbostic /* 197*36564Sbostic * lastix and ixreg track the register indexed addressing 198*36564Sbostic * mode, which is written as <stuff>[reg] but encoded as 199*36564Sbostic * [reg]<stuff>. Only one [reg] is legal. 200*36564Sbostic */ 201*36564Sbostic lastix = NULL; 202*36564Sbostic do { 203*36564Sbostic /* check for special pc-relative (branch) */ 204*36564Sbostic if (A_ACCEXT(optype) & ACCB) { 205*36564Sbostic switch (A_TYPEXT(optype)) { 2068912Srrh case TYPB: 2078912Srrh mode = OC_CONS(OC_BDISP, R_PC); 2083760Sroot break; 2098912Srrh case TYPW: 2108912Srrh mode = OC_CONS(OC_WDISP, R_PC); 2113760Sroot break; 2128912Srrh } 213*36564Sbostic } else 214*36564Sbostic mode = getbyte(); 215*36564Sbostic ixreg = operandout(mode, optype, ins == CHMK); 216*36564Sbostic if (lastix) { 217*36564Sbostic adbprintf("[%s]", lastix); 218*36564Sbostic if (ixreg) 219*36564Sbostic t = 1; 2208912Srrh } 221*36564Sbostic } while ((lastix = ixreg) != NULL); 2223760Sroot } 223*36564Sbostic if (t) 224*36564Sbostic adbprintf("%4t# not code? illegal arguments detected "); 225*36564Sbostic switch (ins) { 226*36564Sbostic case CASEB: 227*36564Sbostic case CASEW: 228*36564Sbostic case CASEL: 229*36564Sbostic if (mapchar == 0 && vset[1] && vset[2]) 230*36564Sbostic casebody(var[1], var[2]); 231*36564Sbostic else 232*36564Sbostic adbprintf("\n%4t# not code? non-constant cases "); 2333760Sroot } 234*36564Sbostic dotinc = dotoff; 2353760Sroot } 2363760Sroot 237*36564Sbostic /* 238*36564Sbostic * Print out the locations to which each of the cases branch. 239*36564Sbostic * This routine carefully allows expressions such as 240*36564Sbostic * 241*36564Sbostic * casel <val>,$<const>,$0x7fffffff 242*36564Sbostic * 243*36564Sbostic * even though they do not fit on a VAX. 244*36564Sbostic */ 245*36564Sbostic static 2468912Srrh casebody(base, limit) 247*36564Sbostic register expr_t base, limit; 2488912Srrh { 249*36564Sbostic register expr_t i = -1; 250*36564Sbostic register addr_t a, baseaddr = inkdot(dotoff); 251*36564Sbostic short displ; 252*36564Sbostic 2538912Srrh argno = 0; 254*36564Sbostic do { 255*36564Sbostic i++; 256*36564Sbostic adbprintf("\n %R: ", base++); 257*36564Sbostic getsomebytes(&displ, sizeof(displ)); 258*36564Sbostic a = displ + baseaddr; 259*36564Sbostic psymoff("%R", a, SP_DATA, maxoff, ""); 260*36564Sbostic savevar(a); 261*36564Sbostic } while (i != limit); 2628912Srrh } 2638912Srrh 2643760Sroot /* 265*36564Sbostic * Handle a normal operand. Return pointer to register 266*36564Sbostic * name if this is an index instruction, else return NULL. 2673760Sroot */ 268*36564Sbostic static char * 269*36564Sbostic operandout(mode, optype, ischmk) 270*36564Sbostic register int mode; 271*36564Sbostic int optype, ischmk; 2728912Srrh { 273*36564Sbostic register char *r; 274*36564Sbostic register int regnumber, nbytes, n; 275*36564Sbostic union { 276*36564Sbostic char b; 277*36564Sbostic short w; 278*36564Sbostic int l; 279*36564Sbostic } displ; 280*36564Sbostic extern char *syscalls[]; 281*36564Sbostic extern int nsys; 2823760Sroot 283*36564Sbostic regnumber = OC_REGEXT(mode); 284*36564Sbostic r = regname[regnumber]; 285*36564Sbostic switch (OC_AMEXT(mode)) { 2868912Srrh 287*36564Sbostic case OC_IMM0: case OC_IMM1: 288*36564Sbostic case OC_IMM2: case OC_IMM3: 289*36564Sbostic savevar(mode); 290*36564Sbostic printc('$'); 291*36564Sbostic #ifdef notyet 292*36564Sbostic if (ty_float[A_TYPEXT(optype)]) 293*36564Sbostic prints(fltimm[mode]); 294*36564Sbostic else if (ischmk && (u_int)mode < nsys && syscalls[mode]) 295*36564Sbostic prints(syscalls[mode]); 296*36564Sbostic else 297*36564Sbostic adbprintf("%V", mode); 298*36564Sbostic #else 299*36564Sbostic switch (A_TYPEXT(optype)) { 3003760Sroot 301*36564Sbostic case TYPF: 302*36564Sbostic case TYPD: 303*36564Sbostic case TYPG: 304*36564Sbostic case TYPH: 305*36564Sbostic prints(fltimm[mode]); 306*36564Sbostic break; 307*36564Sbostic 308*36564Sbostic default: 309*36564Sbostic if (ischmk && (u_int)mode < nsys && syscalls[mode]) 310*36564Sbostic prints(syscalls[mode]); 311*36564Sbostic else 312*36564Sbostic adbprintf("%V", mode); 313*36564Sbostic break; 314*36564Sbostic } 315*36564Sbostic #endif 316*36564Sbostic return (0); 317*36564Sbostic 3188912Srrh case OC_INDEX: 319*36564Sbostic return (r); /* will be printed later */ 320*36564Sbostic 3218912Srrh case OC_REG: 322*36564Sbostic adbprintf("%s", r); 323*36564Sbostic return (0); 324*36564Sbostic 3258912Srrh case OC_DREG: 326*36564Sbostic adbprintf("(%s)", r); 327*36564Sbostic return (0); 328*36564Sbostic 3298912Srrh case OC_ADREG: 330*36564Sbostic adbprintf("-(%s)", r); 331*36564Sbostic return (0); 332*36564Sbostic 3338912Srrh case OC_DAIREG: 3348912Srrh printc('*'); 335*36564Sbostic /* FALLTHROUGH */ 336*36564Sbostic 3378912Srrh case OC_AIREG: 338*36564Sbostic if (regnumber != R_PC) { 339*36564Sbostic adbprintf("(%s)+", r); 340*36564Sbostic return (0); 3418912Srrh } 342*36564Sbostic /* PC immediate */ 343*36564Sbostic printc('$'); 344*36564Sbostic if (mode == OC_CONS(OC_DAIREG, R_PC)) 345*36564Sbostic /* PC absolute, always 4 bytes */ 346*36564Sbostic nbytes = 4; 347*36564Sbostic else { 348*36564Sbostic nbytes = ty_nbyte[A_TYPEXT(optype)]; 349*36564Sbostic if (ty_NORELOC[A_TYPEXT(optype)]) { 350*36564Sbostic bignumprint(nbytes, optype); 351*36564Sbostic return (0); 352*36564Sbostic } 353*36564Sbostic } 354*36564Sbostic break; 355*36564Sbostic 3568912Srrh case OC_DBDISP: 3578912Srrh printc('*'); 358*36564Sbostic /* FALLTHROUGH */ 359*36564Sbostic 3608912Srrh case OC_BDISP: 3618912Srrh nbytes = 1; 3628912Srrh break; 363*36564Sbostic 3648912Srrh case OC_DWDISP: 3658912Srrh printc('*'); 366*36564Sbostic /* FALLTHROUGH */ 367*36564Sbostic 3688912Srrh case OC_WDISP: 3698912Srrh nbytes = 2; 3708912Srrh break; 371*36564Sbostic 3728912Srrh case OC_DLDISP: 3738912Srrh printc('*'); 374*36564Sbostic /* FALLTHROUGH */ 375*36564Sbostic 3768912Srrh case OC_LDISP: 3778912Srrh nbytes = 4; 3788912Srrh break; 379*36564Sbostic 380*36564Sbostic default: 381*36564Sbostic panic("operandout 1"); 382*36564Sbostic /* NOTREACHED */ 3833760Sroot } 3843760Sroot 385*36564Sbostic /* 386*36564Sbostic * Print a displacement format. 387*36564Sbostic */ 388*36564Sbostic getsomebytes(&displ, nbytes); 389*36564Sbostic switch (nbytes) { 390*36564Sbostic case 1: 391*36564Sbostic n = displ.b; 3928912Srrh break; 393*36564Sbostic case 2: 394*36564Sbostic n = displ.w; 395*36564Sbostic break; 396*36564Sbostic case 4: 397*36564Sbostic n = displ.l; 398*36564Sbostic break; 3998912Srrh default: 400*36564Sbostic panic("operandout 2"); 401*36564Sbostic /* NOTREACHED */ 4028912Srrh } 403*36564Sbostic if (regnumber == R_PC) { 404*36564Sbostic switch (OC_AMEXT(mode)) { 4053760Sroot 406*36564Sbostic case OC_DAIREG: 407*36564Sbostic if (ischmk && (u_int)n < nsys && syscalls[n]) { 408*36564Sbostic prints(syscalls[n]); 409*36564Sbostic return (0); 410*36564Sbostic } 411*36564Sbostic break; 4128912Srrh 413*36564Sbostic case OC_BDISP: case OC_DBDISP: 414*36564Sbostic case OC_WDISP: case OC_DWDISP: 415*36564Sbostic case OC_LDISP: case OC_DLDISP: 416*36564Sbostic /* PC offset */ 417*36564Sbostic n += dot + dotoff; 418*36564Sbostic } 419*36564Sbostic psymoff("%V", (addr_t)n, SP_DATA, maxoff, ""); 420*36564Sbostic } else 421*36564Sbostic adbprintf("%V(%s)", (expr_t)n, regname[regnumber]); 422*36564Sbostic savevar(n); 423*36564Sbostic return (0); 4248912Srrh } 4258912Srrh 426*36564Sbostic /* 427*36564Sbostic * Print an F-float, D-float, G-float, H-float, quadword, or octaword. 428*36564Sbostic * F- and D-floating values are printed as themselves, unless they are 429*36564Sbostic * reserved operand bit patterns; these, and the others, are printed 430*36564Sbostic * instead in hex, with leading zeroes suppressed. 431*36564Sbostic */ 432*36564Sbostic static 4338912Srrh bignumprint(nbytes, optype) 434*36564Sbostic int nbytes, optype; 4358912Srrh { 436*36564Sbostic register char *p; 437*36564Sbostic register int i; 438*36564Sbostic union { 439*36564Sbostic float f; /* if f-floating */ 440*36564Sbostic double d; /* if d-floating */ 441*36564Sbostic u_char c[16]; /* if G, H, Q, or O */ 442*36564Sbostic } n; 443*36564Sbostic char expbuf[4*8+1]; /* max 4 8-character hex ints */ 444*36564Sbostic static char tohex[] = "0123456789abcdef"; 4453760Sroot 446*36564Sbostic /* 447*36564Sbostic * Read in the number, then figure out how to print it. 448*36564Sbostic */ 449*36564Sbostic getsomebytes(&n, nbytes); 450*36564Sbostic switch (A_TYPEXT(optype)) { 451*36564Sbostic 452*36564Sbostic case TYPF: 453*36564Sbostic if ((p = checkfloat((caddr_t)&n.f, 0)) == NULL) { 454*36564Sbostic adbprintf("0f%f", n.f); 455*36564Sbostic return; 45635100Sbostic } 457*36564Sbostic adbprintf("%s 0f::", p); 4588912Srrh break; 459*36564Sbostic 4608912Srrh case TYPD: 461*36564Sbostic if ((p = checkfloat((caddr_t)&n.d, 1)) == NULL) { 462*36564Sbostic adbprintf("0d%f", n.d); 463*36564Sbostic return; 46435100Sbostic } 465*36564Sbostic adbprintf("%s 0d::", p); 4668912Srrh break; 467*36564Sbostic 4688912Srrh case TYPG: 469*36564Sbostic adbprintf("0g::"); 470*36564Sbostic break; 471*36564Sbostic 4728912Srrh case TYPH: 473*36564Sbostic adbprintf("0h::"); 474*36564Sbostic break; 475*36564Sbostic 4768912Srrh case TYPQ: 4778912Srrh case TYPO: 4788912Srrh break; 4798912Srrh 480*36564Sbostic default: 481*36564Sbostic panic("bignumprint"); 4828912Srrh } 4838912Srrh 484*36564Sbostic /* 485*36564Sbostic * Expand the number into expbuf, then skip leading zeroes. 486*36564Sbostic * Be careful not to skip the entire number. 487*36564Sbostic */ 488*36564Sbostic for (p = expbuf, i = nbytes; --i >= 0;) { 489*36564Sbostic *p++ = tohex[n.c[i] >> 4]; 490*36564Sbostic *p++ = tohex[n.c[i] & 15]; 4918912Srrh } 492*36564Sbostic for (p = expbuf; *p == '0'; p++) 493*36564Sbostic /* void */; 494*36564Sbostic prints(*p ? p : p - 1); 4958912Srrh } 496