1 /* 2 * @(#)kdb_opset.c 7.3 (Berkeley) 05/26/88 3 */ 4 5 #include "../kdb/defs.h" 6 7 /* 8 * Instruction printing. 9 */ 10 REGLIST reglist [] = { 11 "p1lr", &pcb.pcb_p1lr, "p1br", (int *)&pcb.pcb_p1br, 12 "p0lr", &pcb.pcb_p0lr, "p0br", (int *)&pcb.pcb_p0br, 13 "ksp", &pcb.pcb_ksp, "esp", &pcb.pcb_esp, 14 "ssp", &pcb.pcb_ssp, "psl", &pcb.pcb_psl, 15 "pc", &pcb.pcb_pc, "usp", &pcb.pcb_usp, 16 "fp", &pcb.pcb_fp, "ap", &pcb.pcb_ap, 17 "r11", &pcb.pcb_r11, "r10", &pcb.pcb_r10, 18 "r9", &pcb.pcb_r9, "r8", &pcb.pcb_r8, 19 "r7", &pcb.pcb_r7, "r6", &pcb.pcb_r6, 20 "r5", &pcb.pcb_r5, "r4", &pcb.pcb_r4, 21 "r3", &pcb.pcb_r3, "r2", &pcb.pcb_r2, 22 "r1", &pcb.pcb_r1, "r0", &pcb.pcb_r0, 23 }; 24 25 /* 26 * Argument data types 27 * 28 * If you change these definitions, you must also change the tables 29 * in assizetab.c 30 */ 31 #define TYPB 000 /* byte integer */ 32 #define TYPW 001 /* word integer */ 33 #define TYPL 002 /* long integer */ 34 #define TYPQ 003 /* quad integer */ 35 #define TYPO 004 /* octa integer */ 36 #define TYPF 005 /* F float */ 37 #define TYPD 006 /* D float */ 38 #define TYPG 007 /* G float */ 39 #define TYPH 010 /* H float */ 40 #define TYPUNPACKED 011 /* when unpacked into mantissa & exponent */ 41 #define TYPNONE 012 /* when nothing */ 42 #define TYPLG 4 /* number of bits the above take up */ 43 44 #define TYPMASK ((1<<TYPLG)-1) /* the mask (assumes 2's comp arith) */ 45 /* 46 * Constructors and extractors for argument access kinds and types 47 */ 48 #define A_CONS(access, type) ((access) | (type)) 49 #define A_ACCEXT(consed) ((consed) & (TYPMASK << TYPLG)) 50 #define A_TYPEXT(consed) ((consed) & TYPMASK) 51 52 /* 53 * Argument access types used to test validity of operands to operators 54 */ 55 #define ACCR (1<<TYPLG) /* read */ 56 #define ACCW (2<<TYPLG) /* write */ 57 #define ACCB (4<<TYPLG) /* branch displacement */ 58 #define ACCA (8<<TYPLG) /* address only */ 59 #define ACCV (8<<TYPLG) /* address only */ 60 #define ACCM (ACCR | ACCW) /* modify */ 61 #define ACCI (ACCB | ACCR) /* XFC code */ 62 63 #define ACCESSMASK (ACCA | ACCR | ACCW | ACCB) /* the mask */ 64 65 /* 66 * Construction of TYPX and ACCX, to make the instrs table 67 * easy to use and read. 68 */ 69 /* 70 * For real memory address 71 */ 72 #define A_AB A_CONS(ACCA, TYPB) 73 #define A_AW A_CONS(ACCA, TYPW) 74 #define A_AL A_CONS(ACCA, TYPL) 75 #define A_AQ A_CONS(ACCA, TYPQ) 76 #define A_AO A_CONS(ACCA, TYPO) 77 #define A_AF A_CONS(ACCA, TYPF) 78 #define A_AD A_CONS(ACCA, TYPD) 79 #define A_AG A_CONS(ACCA, TYPG) 80 #define A_AH A_CONS(ACCA, TYPH) 81 /* 82 * For real memory addresses, or register addresses [sic] 83 * 84 * CHEAT! we just call these read access, since 85 * registers are allowed. All field instruction, except insv, 86 * are are read access fields. 87 */ 88 #define A_VB A_CONS(ACCR, TYPB) 89 #define A_VW A_CONS(ACCR, TYPW) 90 #define A_VL A_CONS(ACCR, TYPL) 91 #define A_VQ A_CONS(ACCR, TYPQ) 92 #define A_VO A_CONS(ACCR, TYPO) 93 #define A_VF A_CONS(ACCR, TYPF) 94 #define A_VD A_CONS(ACCR, TYPD) 95 #define A_VG A_CONS(ACCR, TYPG) 96 #define A_VH A_CONS(ACCR, TYPH) 97 /* 98 * For branch displacement 99 */ 100 #define A_BB A_CONS(ACCB, TYPB) 101 #define A_BW A_CONS(ACCB, TYPW) 102 /* 103 * For modification 104 */ 105 #define A_MB A_CONS(ACCM, TYPB) 106 #define A_MW A_CONS(ACCM, TYPW) 107 #define A_ML A_CONS(ACCM, TYPL) 108 #define A_MF A_CONS(ACCM, TYPF) 109 #define A_MD A_CONS(ACCM, TYPD) 110 #define A_MG A_CONS(ACCM, TYPG) 111 #define A_MH A_CONS(ACCM, TYPH) 112 /* 113 * For reading 114 */ 115 #define A_RB A_CONS(ACCR, TYPB) 116 #define A_RW A_CONS(ACCR, TYPW) 117 #define A_RL A_CONS(ACCR, TYPL) 118 #define A_RQ A_CONS(ACCR, TYPQ) 119 #define A_RO A_CONS(ACCR, TYPO) 120 #define A_RF A_CONS(ACCR, TYPF) 121 #define A_RD A_CONS(ACCR, TYPD) 122 #define A_RG A_CONS(ACCR, TYPG) 123 #define A_RH A_CONS(ACCR, TYPH) 124 /* 125 * For writing 126 */ 127 #define A_WB A_CONS(ACCW, TYPB) 128 #define A_WW A_CONS(ACCW, TYPW) 129 #define A_WL A_CONS(ACCW, TYPL) 130 #define A_WQ A_CONS(ACCW, TYPQ) 131 #define A_WO A_CONS(ACCW, TYPO) 132 #define A_WF A_CONS(ACCW, TYPF) 133 #define A_WD A_CONS(ACCW, TYPD) 134 #define A_WG A_CONS(ACCW, TYPG) 135 #define A_WH A_CONS(ACCW, TYPH) 136 137 struct insttab { 138 char *iname; 139 u_char eopcode; 140 u_char popcode; 141 char nargs; 142 u_char argtype[6]; 143 }; 144 145 #define OP(name,eopcode,popdcode,nargs,a1,a2,a3,a4,a5,a6) \ 146 {name,eopcode,popdcode,nargs,a1,a2,a3,a4,a5,a6} 147 /* 148 * Definitions for the escape bytes 149 */ 150 #define CORE 0 151 #define NEW 1 152 #define ESCD 0xfd 153 #define ESCF 0xff 154 #define mapescbyte(b) ((b) == ESCD ? 1 : (b) == ESCF ? 2 : 0) 155 156 static struct insttab insttab[] = { 157 #include "../vax/kdb_instrs" 158 0}; 159 160 /* 161 * Convert TYP[BWLQOFDGH] into {1 if relocation not OK} 162 */ 163 int ty_NORELOC[] = { 164 0, /* TYPB */ 165 0, /* TYPW */ 166 0, /* TYPL */ 167 1, /* TYPQ */ 168 1, /* TYPO */ 169 1, /* TYPF */ 170 1, /* TYPD */ 171 1, /* TYPG */ 172 1, /* TYPH */ 173 1 /* TYPNONE */ 174 }; 175 176 /* 177 * Convert TYP[BWLQOFDGH] into {1 ... 16} 178 */ 179 int ty_nbyte[] = { 180 1, /* TYPB */ 181 2, /* TYPW */ 182 4, /* TYPL */ 183 8, /* TYPQ */ 184 16, /* TYPO */ 185 4, /* TYPF */ 186 8, /* TYPD */ 187 8, /* TYPG */ 188 16, /* TYPH */ 189 0 /* TYPNONE */ 190 }; 191 192 static char *regname[] = { 193 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 194 "r8", "r9", "r10","r11","ap", "fp", "sp", "pc" 195 }; 196 static char *fltimm[] = { 197 "0.5", "0.5625", "0.625", "0.6875", "0.75", "0.8125", "0.875", "0.9375", 198 "1.0", "1.125", "1.25", "1.375", "1.5", "1.625", "1.75", "1.875", 199 "2.0", "2.25", "2.5", "2.75", "3.0", "3.25", "3.5", "3.75", 200 "4.0", "4.5", "5.0", "5.5", "6.0", "6.5", "7.0", "7.5", 201 "8.0", "9.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0", 202 "16.0", "18.0", "20.0", "22.0", "24.0", "26.0", "28.0", "30.0", 203 "32.0", "36.0", "40.0", "44.0", "48.0", "52.0", "56.0", "60.0", 204 "64.0", "72.0", "80.0", "88.0", "96.0", "104.0", "112.0", "120.0" 205 }; 206 207 static int type, space, incp; 208 static long insoutvar[36]; 209 /* 210 * Definitions for registers and for operand classes 211 */ 212 static char *insregname(); /* how to print a register */ 213 214 #define R_PC 0xF 215 216 #define OC_IMM0 0x0 217 #define OC_IMM1 0x1 218 #define OC_IMM2 0x2 219 #define OC_IMM3 0x3 220 #define OC_INDEX 0x4 221 #define OC_REG 0x5 222 #define OC_DREG 0x6 223 #define OC_ADREG 0x7 224 #define OC_AIREG 0x8 225 #define OC_DAIREG 0x9 226 227 #define OC_BDISP 0xA 228 #define OC_DBDISP 0xB 229 #define OC_WDISP 0xC 230 #define OC_DWDISP 0xD 231 #define OC_LDISP 0xE 232 #define OC_DLDISP 0xF 233 234 #define OC_SHIFT 4 235 #define OC_CONS(oc,reg) (((oc & 0xF) << OC_SHIFT) | (reg & 0xF)) 236 #define OC_AMEXT(x) (((x) >> OC_SHIFT) & 0xF) 237 #define OC_REGEXT(x) ((x) & 0xF) 238 239 /* 240 * Definitions for large numbers 241 */ 242 #include "asnumber.h" 243 typedef struct as_number *numberp; 244 static numberp snarf(); 245 static numberp snarfreloc(); 246 /* 247 * Definitions for special instructions 248 */ 249 #define CASEB 0x8F 250 #define CASEW 0xAF 251 #define CASEL 0xCF 252 253 /* two level 1-based index by opcode into insttab */ 254 static short ioptab[3][256]; 255 256 kdbsetup() 257 { 258 register struct insttab *p; 259 int mapchar; 260 261 for(p = insttab; p->iname; p++){ 262 mapchar = mapescbyte(p->eopcode); 263 if (ioptab[mapchar][p->popcode]) 264 continue; 265 ioptab[mapchar][p->popcode] = (p - insttab) + 1; 266 } 267 } 268 269 static u_char snarfuchar(); 270 /* 271 * Global variables for communicating with the minions and printins 272 */ 273 static int idsp; 274 static short argno; /* which argument one is working on */ 275 static char insoutfmt[2]; /* how to format the relocated symbols */ 276 277 static savevar(val) 278 long val; 279 { 280 var[argno] = val; 281 insoutvar[argno] = val; 282 } 283 284 /* ARGSUSED */ 285 printins(fmt, Idsp, ins) 286 char fmt; 287 u_char ins; 288 int Idsp; 289 { 290 u_char mode; /* mode */ 291 u_char ins2; 292 char *indexreg; /* print of which register indexes */ 293 char *indexed; /* we indexed */ 294 char *operandout(); 295 register u_char *ap; 296 register struct insttab *ip; 297 u_char optype; 298 int mapchar; 299 300 idsp = Idsp; 301 type = DSYM; 302 space = idsp; 303 insoutfmt[0] = 0; 304 305 incp = 1; 306 if ((mapchar = mapescbyte(ins)) != 0){ 307 ins2 = snarfuchar(); 308 if (ioptab[mapchar][ins2] == 0){ 309 /* 310 * Oops; not a defined instruction; 311 * back over this escape byte. 312 */ 313 incp -= 1; 314 mapchar = 0; 315 } else { 316 ins = ins2; 317 } 318 } 319 if (ioptab[mapchar][ins] == 0){ 320 printf("<undefined operator byte>: %x", ins); 321 goto ret; 322 } 323 ip = &insttab[ioptab[mapchar][ins] - 1]; 324 printf("%s\t", ip->iname); 325 326 for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++, ap++) { 327 savevar(0x80000000); /* an illegal symbol */ 328 optype = *ap; 329 if (argno != 0) 330 printc(','); 331 indexreg = 0; 332 indexed = 0; 333 do{ 334 if (A_ACCEXT(optype) & ACCB){ 335 switch(A_TYPEXT(optype)){ 336 case TYPB: 337 mode = OC_CONS(OC_BDISP, R_PC); 338 break; 339 case TYPW: 340 mode = OC_CONS(OC_WDISP, R_PC); 341 break; 342 } 343 } else { 344 mode = snarfuchar(); 345 } 346 indexreg = operandout(mode, optype); 347 if (indexed) 348 printf("[%s]", indexed); 349 indexed = indexreg; 350 } while(indexed); 351 } 352 if (mapchar == 0){ 353 switch(ins){ 354 case CASEB: 355 case CASEW: 356 case CASEL: 357 casebody(insoutvar[1], insoutvar[2]); 358 break; 359 default: 360 break; 361 } 362 } 363 ret: ; 364 365 dotinc = incp; 366 } 367 368 casebody(base, limit) 369 long base; 370 long limit; 371 { 372 int i; 373 u_int baseincp; 374 u_int advincp; 375 struct as_number *valuep; 376 #define OSIZE (sizeof(short)) 377 argno = 0; 378 baseincp = incp; 379 for (i = 0; i <= limit; i++) { 380 printc(EOR); 381 printf(" %R: ", i + base); 382 valuep = snarfreloc(OSIZE, 0); 383 advincp = incp; 384 incp = baseincp; 385 dispaddress(valuep, OC_CONS(OC_WDISP, R_PC)); 386 incp = advincp; 387 } 388 } 389 390 /* 391 * magic values to mung an offset to a register into 392 * something that psymoff can understand.. all magic 393 */ 394 /* 0 1 2 3 4 */ 395 static long magic_masks[5] = {0, 0x80, 0x8000, 0, 0}; 396 static long magic_compl[5] = {0, 0x100, 0x10000,0, 0}; 397 /* 398 * Snarf up some bytes, and put in the magic relocation flags 399 */ 400 static numberp snarfreloc(nbytes) 401 int nbytes; 402 { 403 numberp back; 404 back = snarf(nbytes); 405 if (back->num_ulong[0] & magic_masks[nbytes]) 406 back->num_ulong[0] -= magic_compl[nbytes]; 407 return(back); 408 } 409 /* 410 * The following code is NOT portable from the PDP 11 to the VAX 411 * because of the byte ordering problem. 412 */ 413 static numberp snarf(nbytes) 414 int nbytes; 415 { 416 register int i; 417 418 static struct as_number backnumber; 419 static struct as_number znumber; /* init'ed to 0 */ 420 421 backnumber = znumber; 422 for (i = 0; i < nbytes; i++) 423 backnumber.num_uchar[i] = snarfuchar(); 424 return(&backnumber); 425 } 426 427 /* 428 * Read one single character, and advance the dot 429 */ 430 static u_char 431 snarfuchar() 432 { 433 u_char back; 434 /* 435 * assert: bchkget and inkdot don't have side effects 436 */ 437 back = (u_char)bchkget(inkdot(incp), idsp); 438 incp += 1; 439 return(back); 440 } 441 442 /* 443 * normal operand; return non zero pointer to register 444 * name if this is an index instruction. 445 */ 446 char *operandout(mode, optype) 447 u_char mode; 448 u_char optype; 449 { 450 char *r; 451 int regnumber; 452 int nbytes; 453 454 regnumber = OC_REGEXT(mode); 455 r = insregname(regnumber); 456 switch (OC_AMEXT(mode)){ 457 case OC_IMM0: 458 case OC_IMM1: 459 case OC_IMM2: 460 case OC_IMM3: 461 shortliteral(mode, optype); 462 return(0); 463 case OC_INDEX: 464 return(r); /* will be printed later */ 465 case OC_REG: 466 printf("%s", r); 467 return(0); 468 case OC_DREG: 469 printf("(%s)", r); 470 return(0); 471 case OC_ADREG: 472 printf("-(%s)", r); 473 return(0); 474 case OC_DAIREG: 475 printc('*'); 476 case OC_AIREG: 477 if (regnumber == R_PC){ 478 pcimmediate(mode, optype); 479 } else { 480 printf("(%s)+", r); 481 } 482 return(0); 483 case OC_DBDISP: 484 printc('*'); 485 case OC_BDISP: 486 nbytes = 1; 487 break; 488 case OC_DWDISP: 489 printc('*'); 490 case OC_WDISP: 491 nbytes = 2; 492 break; 493 case OC_DLDISP: 494 printc('*'); 495 case OC_LDISP: 496 nbytes = 4; 497 break; 498 } 499 dispaddress(snarfreloc(nbytes), mode); 500 return(0); 501 } 502 503 dispaddress(valuep, mode) 504 numberp valuep; 505 u_char mode; 506 { 507 int regnumber = OC_REGEXT(mode); 508 509 switch(OC_AMEXT(mode)){ 510 case OC_BDISP: 511 case OC_DBDISP: 512 case OC_WDISP: 513 case OC_DWDISP: 514 case OC_LDISP: 515 case OC_DLDISP: 516 if (regnumber == R_PC){ 517 /* PC offset addressing */ 518 valuep->num_ulong[0] += inkdot(incp); 519 } 520 } 521 if (regnumber == R_PC) 522 psymoff(valuep->num_ulong[0], type, &insoutfmt[0]); 523 else { /* } */ 524 printf(LPRMODE, valuep->num_ulong[0]); 525 printf(insoutfmt); 526 printf("(%s)", insregname(regnumber)); 527 } 528 savevar((long)valuep->num_ulong[0]); 529 } 530 531 /* 532 * get a register name 533 */ 534 static char * 535 insregname(regnumber) 536 int regnumber; 537 { 538 char *r; 539 r = regname[regnumber]; 540 return(r); 541 } 542 543 /* 544 * print out a short literal 545 */ 546 shortliteral(mode, optype) 547 u_char mode; 548 u_char optype; 549 { 550 savevar((long)mode); 551 switch(A_TYPEXT(optype)){ 552 case TYPF: 553 case TYPD: 554 case TYPG: 555 case TYPH: 556 printf("$%s", fltimm[mode]); 557 break; 558 default: 559 printf("$%r", mode); 560 break; 561 } 562 } 563 564 pcimmediate(mode, optype) 565 u_char mode; 566 u_char optype; 567 { 568 int nbytes; 569 570 printc('$'); 571 if (mode == OC_CONS(OC_DAIREG, R_PC)){ /* PC absolute, always 4 bytes*/ 572 dispaddress(snarfreloc(4), mode); 573 return; 574 } 575 nbytes = ty_nbyte[A_TYPEXT(optype)]; 576 if (! ty_NORELOC[A_TYPEXT(optype)]){ 577 dispaddress(snarfreloc(nbytes), mode); 578 return; 579 } 580 bignumprint(nbytes, optype); 581 } 582 583 bignumprint(nbytes, optype) 584 int nbytes; 585 u_char optype; 586 { 587 numberp valuep; 588 int leading_zero = 1; 589 register int bindex; 590 register int nindex; 591 register int ch; 592 593 valuep = snarf(nbytes); 594 switch(A_TYPEXT(optype)){ 595 case TYPF: 596 printf("0f%f", valuep->num_num.numFf_float.Ff_value); 597 break; 598 case TYPD: 599 printf("0d%f", valuep->num_num.numFd_float.Fd_value); 600 break; 601 case TYPG: 602 printf("0g::"); goto qprint; 603 case TYPH: 604 printf("0h::"); goto qprint; 605 case TYPQ: 606 case TYPO: 607 qprint: 608 for (bindex = nbytes - 1; bindex >= 0; --bindex){ 609 for (nindex = 4; nindex >= 0; nindex -= 4){ 610 ch = (valuep->num_uchar[bindex] >> nindex); 611 ch &= 0x0F; 612 if ( ! (leading_zero &= (ch == 0) ) ){ 613 if (ch <= 0x09) 614 printc(ch + '0'); 615 else 616 printc(ch - 0x0A + 'a'); 617 } 618 } 619 } 620 break; 621 } 622 } 623