1 /* 2 * @(#)kdb_opset.c 7.2 (Berkeley) 05/07/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 printins(fmt, Idsp, ins) 285 char fmt; 286 u_char ins; 287 int Idsp; 288 { 289 u_char mode; /* mode */ 290 u_char ins2; 291 char *indexreg; /* print of which register indexes */ 292 char *indexed; /* we indexed */ 293 char *operandout(); 294 register u_char *ap; 295 register struct insttab *ip; 296 u_char optype; 297 int mapchar; 298 299 idsp = Idsp; 300 type = DSYM; 301 space = idsp; 302 insoutfmt[0] = 0; 303 304 incp = 1; 305 if ((mapchar = mapescbyte(ins)) != 0){ 306 ins2 = snarfuchar(); 307 if (ioptab[mapchar][ins2] == 0){ 308 /* 309 * Oops; not a defined instruction; 310 * back over this escape byte. 311 */ 312 incp -= 1; 313 mapchar = 0; 314 } else { 315 ins = ins2; 316 } 317 } 318 if (ioptab[mapchar][ins] == 0){ 319 printf("<undefined operator byte>: %x", ins); 320 goto ret; 321 } 322 ip = &insttab[ioptab[mapchar][ins] - 1]; 323 printf("%s\t", ip->iname); 324 325 for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++, ap++) { 326 savevar(0x80000000); /* an illegal symbol */ 327 optype = *ap; 328 if (argno != 0) 329 printc(','); 330 indexreg = 0; 331 indexed = 0; 332 do{ 333 if (A_ACCEXT(optype) & ACCB){ 334 switch(A_TYPEXT(optype)){ 335 case TYPB: 336 mode = OC_CONS(OC_BDISP, R_PC); 337 break; 338 case TYPW: 339 mode = OC_CONS(OC_WDISP, R_PC); 340 break; 341 } 342 } else { 343 mode = snarfuchar(); 344 } 345 indexreg = operandout(mode, optype); 346 if (indexed) 347 printf("[%s]", indexed); 348 indexed = indexreg; 349 } while(indexed); 350 } 351 if (mapchar == 0){ 352 switch(ins){ 353 case CASEB: 354 case CASEW: 355 case CASEL: 356 casebody(insoutvar[1], insoutvar[2]); 357 break; 358 default: 359 break; 360 } 361 } 362 ret: ; 363 364 dotinc = incp; 365 } 366 367 casebody(base, limit) 368 long base; 369 long limit; 370 { 371 int i; 372 u_int baseincp; 373 u_int advincp; 374 struct as_number *valuep; 375 #define OSIZE (sizeof(short)) 376 argno = 0; 377 baseincp = incp; 378 for (i = 0; i <= limit; i++) { 379 printc(EOR); 380 printf(" %R: ", i + base); 381 valuep = snarfreloc(OSIZE, 0); 382 advincp = incp; 383 incp = baseincp; 384 dispaddress(valuep, OC_CONS(OC_WDISP, R_PC)); 385 incp = advincp; 386 } 387 } 388 389 /* 390 * magic values to mung an offset to a register into 391 * something that psymoff can understand.. all magic 392 */ 393 /* 0 1 2 3 4 */ 394 static long magic_masks[5] = {0, 0x80, 0x8000, 0, 0}; 395 static long magic_compl[5] = {0, 0x100, 0x10000,0, 0}; 396 /* 397 * Snarf up some bytes, and put in the magic relocation flags 398 */ 399 static numberp snarfreloc(nbytes) 400 int nbytes; 401 { 402 numberp back; 403 back = snarf(nbytes); 404 if (back->num_ulong[0] & magic_masks[nbytes]) 405 back->num_ulong[0] -= magic_compl[nbytes]; 406 return(back); 407 } 408 /* 409 * The following code is NOT portable from the PDP 11 to the VAX 410 * because of the byte ordering problem. 411 */ 412 static numberp snarf(nbytes) 413 int nbytes; 414 { 415 register int i; 416 417 static struct as_number backnumber; 418 static struct as_number znumber; /* init'ed to 0 */ 419 420 backnumber = znumber; 421 for (i = 0; i < nbytes; i++) 422 backnumber.num_uchar[i] = snarfuchar(); 423 return(&backnumber); 424 } 425 426 /* 427 * Read one single character, and advance the dot 428 */ 429 static u_char 430 snarfuchar() 431 { 432 u_char back; 433 /* 434 * assert: bchkget and inkdot don't have side effects 435 */ 436 back = (u_char)bchkget(inkdot(incp), idsp); 437 incp += 1; 438 return(back); 439 } 440 441 /* 442 * normal operand; return non zero pointer to register 443 * name if this is an index instruction. 444 */ 445 char *operandout(mode, optype) 446 u_char mode; 447 u_char optype; 448 { 449 char *r; 450 int regnumber; 451 int nbytes; 452 453 regnumber = OC_REGEXT(mode); 454 r = insregname(regnumber); 455 switch (OC_AMEXT(mode)){ 456 case OC_IMM0: 457 case OC_IMM1: 458 case OC_IMM2: 459 case OC_IMM3: 460 shortliteral(mode, optype); 461 return(0); 462 case OC_INDEX: 463 return(r); /* will be printed later */ 464 case OC_REG: 465 printf("%s", r); 466 return(0); 467 case OC_DREG: 468 printf("(%s)", r); 469 return(0); 470 case OC_ADREG: 471 printf("-(%s)", r); 472 return(0); 473 case OC_DAIREG: 474 printc('*'); 475 case OC_AIREG: 476 if (regnumber == R_PC){ 477 pcimmediate(mode, optype); 478 } else { 479 printf("(%s)+", r); 480 } 481 return(0); 482 case OC_DBDISP: 483 printc('*'); 484 case OC_BDISP: 485 nbytes = 1; 486 break; 487 case OC_DWDISP: 488 printc('*'); 489 case OC_WDISP: 490 nbytes = 2; 491 break; 492 case OC_DLDISP: 493 printc('*'); 494 case OC_LDISP: 495 nbytes = 4; 496 break; 497 } 498 dispaddress(snarfreloc(nbytes), mode); 499 return(0); 500 } 501 502 dispaddress(valuep, mode) 503 numberp valuep; 504 u_char mode; 505 { 506 int regnumber = OC_REGEXT(mode); 507 508 switch(OC_AMEXT(mode)){ 509 case OC_BDISP: 510 case OC_DBDISP: 511 case OC_WDISP: 512 case OC_DWDISP: 513 case OC_LDISP: 514 case OC_DLDISP: 515 if (regnumber == R_PC){ 516 /* PC offset addressing */ 517 valuep->num_ulong[0] += inkdot(incp); 518 } 519 } 520 if (regnumber == R_PC) 521 psymoff(valuep->num_ulong[0], type, &insoutfmt[0]); 522 else { /* } */ 523 printf(LPRMODE, valuep->num_ulong[0]); 524 printf(insoutfmt); 525 printf("(%s)", insregname(regnumber)); 526 } 527 savevar((long)valuep->num_ulong[0]); 528 } 529 530 /* 531 * get a register name 532 */ 533 static char * 534 insregname(regnumber) 535 int regnumber; 536 { 537 char *r; 538 r = regname[regnumber]; 539 return(r); 540 } 541 542 /* 543 * print out a short literal 544 */ 545 shortliteral(mode, optype) 546 u_char mode; 547 u_char optype; 548 { 549 savevar((long)mode); 550 switch(A_TYPEXT(optype)){ 551 case TYPF: 552 case TYPD: 553 case TYPG: 554 case TYPH: 555 printf("$%s", fltimm[mode]); 556 break; 557 default: 558 printf("$%r", mode); 559 break; 560 } 561 } 562 563 pcimmediate(mode, optype) 564 u_char mode; 565 u_char optype; 566 { 567 int nbytes; 568 569 printc('$'); 570 if (mode == OC_CONS(OC_DAIREG, R_PC)){ /* PC absolute, always 4 bytes*/ 571 dispaddress(snarfreloc(4), mode); 572 return; 573 } 574 nbytes = ty_nbyte[A_TYPEXT(optype)]; 575 if (! ty_NORELOC[A_TYPEXT(optype)]){ 576 dispaddress(snarfreloc(nbytes), mode); 577 return; 578 } 579 bignumprint(nbytes, optype); 580 } 581 582 bignumprint(nbytes, optype) 583 int nbytes; 584 u_char optype; 585 { 586 numberp valuep; 587 int leading_zero = 1; 588 register int bindex; 589 register int nindex; 590 register int ch; 591 592 valuep = snarf(nbytes); 593 switch(A_TYPEXT(optype)){ 594 case TYPF: 595 printf("0f%f", valuep->num_num.numFf_float.Ff_value); 596 break; 597 case TYPD: 598 printf("0d%f", valuep->num_num.numFd_float.Fd_value); 599 break; 600 case TYPG: 601 printf("0g::"); goto qprint; 602 case TYPH: 603 printf("0h::"); goto qprint; 604 case TYPQ: 605 case TYPO: 606 qprint: 607 for (bindex = nbytes - 1; bindex >= 0; --bindex){ 608 for (nindex = 4; nindex >= 0; nindex -= 4){ 609 ch = (valuep->num_uchar[bindex] >> nindex); 610 ch &= 0x0F; 611 if ( ! (leading_zero &= (ch == 0) ) ){ 612 if (ch <= 0x09) 613 printc(ch + '0'); 614 else 615 printc(ch - 0x0A + 'a'); 616 } 617 } 618 } 619 break; 620 } 621 } 622