1 /* $NetBSD: db_disasm.c,v 1.10 2000/08/09 20:00:30 tv Exp $ */ 2 3 /* 4 * Mach Operating System 5 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University 6 * All Rights Reserved. 7 * 8 * Permission to use, copy, modify and distribute this software and its 9 * documentation is hereby granted, provided that both the copyright 10 * notice and this permission notice appear in all copies of the 11 * software, derivative works or modified versions, and any portions 12 * thereof, and that both notices appear in supporting documentation. 13 * 14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17 * 18 * Carnegie Mellon requests users of this software to return to 19 * 20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 21 * School of Computer Science 22 * Carnegie Mellon University 23 * Pittsburgh PA 15213-3890 24 * 25 * any improvements or extensions that they make and grant Carnegie Mellon 26 * the rights to redistribute these changes. 27 */ 28 29 /* 30 * File: db_disasm.c 31 * Author: Alessandro Forin, Carnegie Mellon University 32 * Date: 11/91 33 * 34 * Disassembler for Alpha 35 * 36 * Modified for NetBSD/alpha by: 37 * 38 * Christopher G. Demetriou, Carnegie Mellon University 39 * 40 * Jason R. Thorpe, Numerical Aerospace Simulation Facility, 41 * NASA Ames Research Center 42 * 43 * This code was derived exclusively from information available in 44 * "Alpha Architecture Reference Manual", Richard L. Sites ed. 45 * Digital Press, Burlington, MA 01803 46 * ISBN 1-55558-098-X, Order no. EY-L520E-DP 47 */ 48 49 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 50 51 __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.10 2000/08/09 20:00:30 tv Exp $"); 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/proc.h> 56 #include <machine/db_machdep.h> 57 #include <alpha/alpha/db_instruction.h> 58 59 #include <machine/pal.h> 60 61 #include <ddb/db_access.h> 62 #include <ddb/db_sym.h> 63 #include <ddb/db_output.h> 64 #include <ddb/db_interface.h> 65 66 /* 67 * This would belong in a header file, except noone else needs it 68 * 69 * XXX THESE SHOULD BE CONVERTED TO ra, rb, rc FORMAT. 70 */ 71 typedef union { 72 /* 73 * All instructions are 32 bits wide, PAL included 74 */ 75 unsigned int bits; 76 77 /* 78 * Internal processor register access instrs 79 * specify the IPR index, doubly specify the 80 * (same) GP register as src/dest, and qualifiers 81 * for the IPR set involved (abox/ibox/tmp) 82 */ 83 struct { 84 unsigned index : 5, 85 regset : 3, /* a,i,p */ 86 xxx : 8, 87 rs : 5, 88 rd : 5, 89 opcode : 6; 90 } mXpr_format; 91 92 /* 93 * Load/store instructions have a 12 bit displacement, 94 * and two register specifiers just as normal ld/st. 95 * Four bits have special meanings: 96 * phy: bypass the MMU (physical access) 97 * alt: use mode in ALT register for checks, 98 * or if PHY is also on locked/linked access 99 * rwc: read-with-write-check (probew) 100 * qw: quadword access 101 */ 102 struct { 103 signed int displacement : 12; 104 unsigned qw : 1, 105 qualif : 3, 106 rs : 5, 107 rd : 5, 108 opcode : 6; 109 } mem_format; 110 111 /* 112 * Return from exception or interrupt has 113 * a branch-like encoding, but only one 114 * instantiation is actually usable. 115 */ 116 struct { 117 unsigned xxx : 14, 118 zero : 1, /* branch prediction! */ 119 one : 1, 120 rb : 5, /* r31 or stall */ 121 ra : 5, /* r31 or stall */ 122 opcode : 6; 123 } rei_format; 124 125 } pal_instruction; 126 127 /* 128 * Major opcodes 129 */ 130 static char *op_name[64] = { 131 /* 0 */ "call_pal", "op1", "op2", "op3", "op4", "op5", "op6", "op7", 132 /* 8 */ "lda", "ldah", "ldbu", "ldq_u","ldwu", "stw", "stb", "stq_u", 133 /*16 */ "arit", "logical","bit","mul", "op20", "vaxf", "ieeef","anyf", 134 /*24 */ "spec", "hw_mfpr","jump","hw_ld","intmisc","hw_mtpr","hw_rei","hw_st", 135 /*32 */ "ldf", "ldg", "lds", "ldt", "stf", "stg", "sts", "stt", 136 /*40 */ "ldl", "ldq", "ldl_l","ldq_l","stl", "stq", "stl_c","stq_c", 137 /*48 */ "br", "fbeq", "fblt", "fble", "bsr", "fbne", "fbge", "fbgt", 138 /*56 */ "blbc", "beq", "blt", "ble", "blbs", "bne", "bge", "bgt" 139 }; 140 141 /* 142 * The function field is too big (7 or 11 bits), so the sub-tables 143 * are addressed in a somewhat complicated manner to save 144 * space. After all, alu operations is what RISCs are good at. 145 */ 146 147 struct tbl { 148 const char *name; 149 int code; 150 }; 151 152 static const struct tbl pal_op_tbl[] = { 153 /* Common PAL function codes. */ 154 { "halt", PAL_halt }, 155 { "cflush", PAL_cflush }, 156 { "draina", PAL_draina }, 157 { "cserve", PAL_cserve, }, 158 { "swppal", PAL_swppal }, 159 { "ipir", PAL_ipir }, 160 { "bpt", PAL_bpt }, 161 { "bugchk", PAL_bugchk }, 162 { "imb", PAL_imb }, 163 { "rdunique", PAL_rdunique }, 164 { "wrunique", PAL_wrunique }, 165 { "gentrap", PAL_gentrap }, 166 167 /* OSF/1 PAL function codes. */ 168 { "osf1_rdmces", PAL_OSF1_rdmces }, 169 { "osf1_wrmces", PAL_OSF1_wrmces }, 170 { "osf1_wrfen", PAL_OSF1_wrfen }, 171 { "osf1_wrvptptr", PAL_OSF1_wrvptptr }, 172 { "osf1_swpctx", PAL_OSF1_swpctx }, 173 { "osf1_wrval", PAL_OSF1_wrval }, 174 { "osf1_rdval", PAL_OSF1_rdval }, 175 { "osf1_tbi", PAL_OSF1_tbi }, 176 { "osf1_wrent", PAL_OSF1_wrent }, 177 { "osf1_swpipl", PAL_OSF1_swpipl }, 178 { "osf1_rdps", PAL_OSF1_rdps }, 179 { "osf1_wrkgp", PAL_OSF1_wrkgp }, 180 { "osf1_wrusp", PAL_OSF1_wrusp }, 181 { "osf1_wrperfmon", PAL_OSF1_wrperfmon }, 182 { "osf1_rdusp", PAL_OSF1_rdusp }, 183 { "osf1_whami", PAL_OSF1_whami }, 184 { "osf1_retsys", PAL_OSF1_retsys }, 185 { "osf1_rti", PAL_OSF1_rti }, 186 { "osf1_callsys", PAL_OSF1_callsys }, 187 188 { NULL, -1 }, 189 }; 190 191 static const char * 192 pal_opname(int op) 193 { 194 static char unk[8]; 195 int i; 196 197 for (i = 0; pal_op_tbl[i].name != NULL; i++) { 198 if (pal_op_tbl[i].code == op) 199 return (pal_op_tbl[i].name); 200 } 201 202 sprintf(unk, "0x%x", op); 203 return (unk); 204 } 205 206 /* HW (PAL) instruction qualifiers, stright tables */ 207 static const char *mXpr_name[8] = { 208 "", "/i", "/a", "/ai", "/p", "/pi", "/pa", "/pai" 209 }; 210 static const char *hwlds_name[8] = { 211 "", "/r", "/a", "/ar", "/p", "/p?r", "_l-c", "_l-c/?r" 212 }; 213 214 /* 215 * For this one we take the low nibble (valid values 0/2/9/b/d) 216 * and shift it down one to get the row index. Within a row 217 * we can just take the high nibble deprived of the high bit 218 * (valid values 0/1/2/3/4/6). We could have used a flat 64 219 * entry array, but in this way we use just 48 pointers. 220 * BUGFIX: the 'cmpbge 0x0f' opcode fits in here too 221 */ 222 static const char *arit_c0[8] = { 223 "addl", 0, "addq", 0, "addl/v", 0, "addq/v", 224 }; 225 static const char *arit_c2[8] = { 226 "s4addl", "s8addl", "s4addq", "s8addq", 227 }; 228 static const char *arit_c9[8] = { 229 "subl", 0, "subq", 0, "subl/v", 0, "subq/v", 230 }; 231 static const char *arit_cB[8] = { 232 "s4subl", "s8subl", "s4subq", "s8subq", 233 }; 234 static const char *arit_cD[8] = { 235 0, "cmpult", "cmpeq", "cmpule", "cmplt", 0, "cmple", 236 }; 237 static const char *arit_cF[1] = { 238 "cmpbge" 239 }; 240 static const char **arit_opname[8] = { 241 arit_c0, arit_c2, 0, 0, arit_c9, arit_cB, arit_cD, arit_cF 242 }; 243 244 static const char * 245 arit_name(int op) 246 { 247 static char unk[32]; 248 const char *name = NULL; 249 250 if (arit_opname[((op)&0xe)>>1]) 251 name = arit_opname[((op)&0xe)>>1][((op)&0x70)>>4]; 252 253 if (name != NULL) 254 return (name); 255 256 sprintf(unk, "?arit 0x%x?", op); 257 return (unk); 258 } 259 260 /* 261 * Something similar for this one, except there are only 262 * 16 entries so the row indexing is done by enumeration 263 * of the low nibble (valid values 0/4/6/8). Then we can 264 * just shift the high nibble to index inside the row 265 * (valid values are 0/2/4 or 1/2/4/6) 266 * 267 * There are two functions that don't play by these simple rules, 268 * so we special-case them. 269 */ 270 static const char *logical_c0[4] = { 271 "and", "or", "xor", 0 272 }; 273 static const char *logical_c4[4] = { 274 "cmovlbs", "cmoveq", "cmovlt", "cmovle" 275 }; 276 static const char *logical_c6[4] = { 277 "cmovlbc", "cmovne", "cmovge", "cmovgt" 278 }; 279 static const char *logical_c8[4] = { 280 "andnot", "ornot", "xornot", 0 281 }; 282 283 static const char * 284 logical_name(int op) 285 { 286 static char unk[32]; 287 const char *name = NULL; 288 289 if (op == op_amask) 290 return ("amask"); 291 else if (op == op_implver) 292 return ("implver"); 293 294 switch (op & 0xf) { 295 case 0: name = logical_c0[((op)>>5)&3]; break; 296 case 4: name = logical_c4[((op)>>5)&3]; break; 297 case 6: name = logical_c6[((op)>>5)&3]; break; 298 case 8: name = logical_c8[((op)>>5)&3]; break; 299 } 300 301 if (name != NULL) 302 return (name); 303 304 sprintf(unk, "?logical 0x%x?", op); 305 return (unk); 306 } 307 308 /* 309 * This is the messy one. First, we single out the dense 310 * case of a 3 in the high nibble (valid values 0/1/2/4/6/9/b/c). 311 * Then the case of a 2 in the low nibble (valid values 0/1/2/5/6/7). 312 * For the remaining codes (6/7/a/b) we do as above: high 313 * nibble has valid values 0/1/2 or 5/6/7. The low nibble 314 * can be used as row index picking bits 0 and 2, for the 315 * high one just the lower two bits. 316 */ 317 static const char *bitop_c3[8] = { 318 "zapnot", "mskql", "srl", "extql", "sll", "insql", "sra", 0 319 }; 320 static const char *bitop_c2[8] = { 321 "mskbl", "mskwl", "mskll", 0/*mskql*/, 0, "mskwh", "msklh", "mskqh" 322 }; 323 static const char *bitop_c67ab[4][4] = { 324 /* a */ { 0, "extwh", "extlh", "extqh"}, 325 /* b */ { "insbl", "inswl", "insll", 0 }, 326 /* 6 */ { "extbl", "extwl", "extll", 0 }, 327 /* 7 */ { 0, "inswh", "inslh", "insqh" }, 328 }; 329 330 static const char * 331 bitop_name(int op) 332 { 333 static char unk[32]; 334 const char *name = NULL; 335 336 if ((op & 0x70) == 0x30) 337 name = (op == op_zap) ? "zap" : bitop_c3[((op)&0xe)>>1]; 338 else if ((op & 0xf) == 0x02) 339 name = bitop_c2[(op)>>4]; 340 else 341 name = 342 bitop_c67ab[(((op)&1)|(((op)&0x4)>>1))][(((op)&0x30)>>4)]; 343 344 if (name != NULL) 345 return (name); 346 347 sprintf(unk, "?bit 0x%x?", op); 348 return (unk); 349 } 350 351 /* 352 * Only 5 entries in this one 353 */ 354 static const char *mul_opname[4] = { 355 "mull", "mulq", "mull/v", "mulq/v" 356 }; 357 358 static const char * 359 mul_name(int op) 360 { 361 static char unk[32]; 362 const char *name = NULL; 363 364 name = (op == op_umulh) ? "umulh" : mul_opname[((op)>>5)&3]; 365 366 if (name != NULL) 367 return (name); 368 369 sprintf(unk, "?mul 0x%x?", op); 370 return (unk); 371 } 372 373 /* 374 * These are few, the high nibble is usually enough to dispatch. 375 * We single out the `f' case to halve the table size, as 376 * well as the cases in which the high nibble isn't enough. 377 */ 378 static const char *special_opname[8] = { 379 "trapb", 0, "mb", 0, "fetch", "fetch_m", "rpcc", "rc" 380 }; 381 382 static const char * 383 special_name(int op) 384 { 385 static char unk[32]; 386 const char *name; 387 388 switch (op) { 389 case op_excb: name = "excb"; break; 390 case op_wmb: name = "wmb"; break; 391 case op_ecb: name = "ecb"; break; 392 case op_rs: name = "rs"; break; 393 case op_wh64: name = "wh64"; break; 394 default: 395 name = special_opname[(op)>>13]; 396 } 397 398 if (name != NULL) 399 return (name); 400 401 sprintf(unk, "?special 0x%x?", op); 402 return (unk); 403 } 404 405 /* 406 * This is trivial 407 */ 408 static const char *jump_opname[4] = { 409 "jmp", "jsr", "ret", "jcr" 410 }; 411 #define jump_name(ix) jump_opname[ix] 412 413 /* 414 * For all but 4 of these, we can dispatch on the lower nibble of 415 * the "function". 416 */ 417 static const char *intmisc_opname_3x[16] = { 418 "ctpop", "perr", "ctlz", "cttz", "unpkbw", "unpkbl", "pkwb", 419 "pklb", "minsb8", "minsw4", "minub8", "minuw4", "maxub8", 420 "maxuw4", "maxsb8", "maxsw4", 421 }; 422 423 static const char * 424 intmisc_name(int op) 425 { 426 static char unk[32]; 427 428 if ((op & 0xf0) == 0x30) 429 return (intmisc_opname_3x[op & 0x0f]); 430 431 switch (op) { 432 case op_sextb: return ("sextb"); 433 case op_sextw: return ("sextw"); 434 case op_ftoit: return ("ftoit"); 435 case op_ftois: return ("ftois"); 436 } 437 438 sprintf(unk, "?intmisc 0x%x?", op); 439 return (unk); 440 } 441 442 static const char * 443 float_name(const struct tbl *tbl, int op, const char *type) 444 { 445 static char unk[32]; 446 int i; 447 448 for (i = 0; tbl[i].name != NULL; i++) { 449 if (tbl[i].code == op) 450 return (tbl[i].name); 451 } 452 453 sprintf(unk, "?%s 0x%x?", type, op); 454 return (unk); 455 } 456 457 #define vaxf_name(op) float_name(vaxf_tbl, op, "vaxfl") 458 #define ieeef_name(op) float_name(ieeef_tbl, op, "ieeefl") 459 #define anyf_name(op) float_name(anyf_tbl, op, "anyfl") 460 461 static const struct tbl anyf_tbl[] = { 462 { "cvtlq", 0x010}, 463 { "cpys", 0x020}, 464 { "cpysn", 0x021}, 465 { "cpyse", 0x022}, 466 { "mt_fpcr", 0x024}, 467 { "mf_fpcr", 0x025}, 468 { "fcmoveq", 0x02a}, 469 { "fcmovne", 0x02b}, 470 { "fcmovlt", 0x02c}, 471 { "fcmovge", 0x02d}, 472 { "fcmovle", 0x02e}, 473 { "fcmovgt", 0x02f}, 474 { "cvtql", 0x030}, 475 { "cvtql/v", 0x130}, 476 { "cvtql/sv", 0x330}, 477 { 0, 0}, 478 }; 479 480 static const struct tbl ieeef_tbl[] = { 481 { "adds/c", 0x000}, 482 { "subs/c", 0x001}, 483 { "muls/c", 0x002}, 484 { "divs/c", 0x003}, 485 { "addt/c", 0x020}, 486 { "subt/c", 0x021}, 487 { "mult/c", 0x022}, 488 { "divt/c", 0x023}, 489 { "cvtts/c", 0x02c}, 490 { "cvttq/c", 0x02f}, 491 { "cvtqs/c", 0x03c}, 492 { "cvtqt/c", 0x03e}, 493 { "adds/m", 0x040}, 494 { "subs/m", 0x041}, 495 { "muls/m", 0x042}, 496 { "divs/m", 0x043}, 497 { "addt/m", 0x060}, 498 { "subt/m", 0x061}, 499 { "mult/m", 0x062}, 500 { "divt/m", 0x063}, 501 { "cvtts/m", 0x06c}, 502 { "cvtqs/m", 0x07c}, 503 { "cvtqt/m", 0x07e}, 504 { "adds", 0x080}, 505 { "subs", 0x081}, 506 { "muls", 0x082}, 507 { "divs", 0x083}, 508 { "addt", 0x0a0}, 509 { "subt", 0x0a1}, 510 { "mult", 0x0a2}, 511 { "divt", 0x0a3}, 512 { "cmptun", 0x0a4}, 513 { "cmpteq", 0x0a5}, 514 { "cmptlt", 0x0a6}, 515 { "cmptle", 0x0a7}, 516 { "cvtts", 0x0ac}, 517 { "cvttq", 0x0af}, 518 { "cvtqs", 0x0bc}, 519 { "cvtqt", 0x0be}, 520 { "adds/d", 0x0c0}, 521 { "subs/d", 0x0c1}, 522 { "muls/d", 0x0c2}, 523 { "divs/d", 0x0c3}, 524 { "addt/d", 0x0e0}, 525 { "subt/d", 0x0e1}, 526 { "mult/d", 0x0e2}, 527 { "divt/d", 0x0e3}, 528 { "cvtts/d", 0x0ec}, 529 { "cvtqs/d", 0x0fc}, 530 { "cvtqt/d", 0x0fe}, 531 { "adds/uc", 0x100}, 532 { "subs/uc", 0x101}, 533 { "muls/uc", 0x102}, 534 { "divs/uc", 0x103}, 535 { "addt/uc", 0x120}, 536 { "subt/uc", 0x121}, 537 { "mult/uc", 0x122}, 538 { "divt/uc", 0x123}, 539 { "cvtts/uc", 0x12c}, 540 { "cvttq/vc", 0x12f}, 541 { "adds/um", 0x140}, 542 { "subs/um", 0x141}, 543 { "muls/um", 0x142}, 544 { "divs/um", 0x143}, 545 { "addt/um", 0x160}, 546 { "subt/um", 0x161}, 547 { "mult/um", 0x162}, 548 { "divt/um", 0x163}, 549 { "cvtts/um", 0x16c}, 550 { "adds/u", 0x180}, 551 { "subs/u", 0x181}, 552 { "muls/u", 0x182}, 553 { "divs/u", 0x183}, 554 { "addt/u", 0x1a0}, 555 { "subt/u", 0x1a1}, 556 { "mult/u", 0x1a2}, 557 { "divt/u", 0x1a3}, 558 { "cvtts/u", 0x1ac}, 559 { "cvttq/v", 0x1af}, 560 { "adds/ud", 0x1c0}, 561 { "subs/ud", 0x1c1}, 562 { "muls/ud", 0x1c2}, 563 { "divs/ud", 0x1c3}, 564 { "addt/ud", 0x1e0}, 565 { "subt/ud", 0x1e1}, 566 { "mult/ud", 0x1e2}, 567 { "divt/ud", 0x1e3}, 568 { "cvtts/ud", 0x1ec}, 569 { "adds/suc", 0x500}, 570 { "subs/suc", 0x501}, 571 { "muls/suc", 0x502}, 572 { "divs/suc", 0x503}, 573 { "addt/suc", 0x520}, 574 { "subt/suc", 0x521}, 575 { "mult/suc", 0x522}, 576 { "divt/suc", 0x523}, 577 { "cvtts/suc", 0x52c}, 578 { "cvttq/svc", 0x52f}, 579 { "adds/sum", 0x540}, 580 { "subs/sum", 0x541}, 581 { "muls/sum", 0x542}, 582 { "divs/sum", 0x543}, 583 { "addt/sum", 0x560}, 584 { "subt/sum", 0x561}, 585 { "mult/sum", 0x562}, 586 { "divt/sum", 0x563}, 587 { "cvtts/sum", 0x56c}, 588 { "adds/su", 0x580}, 589 { "subs/su", 0x581}, 590 { "muls/su", 0x582}, 591 { "divs/su", 0x583}, 592 { "addt/su", 0x5a0}, 593 { "subt/su", 0x5a1}, 594 { "mult/su", 0x5a2}, 595 { "divt/su", 0x5a3}, 596 { "cmptun/su", 0x5a4}, 597 { "cmpteq/su", 0x5a5}, 598 { "cmptlt/su", 0x5a6}, 599 { "cmptle/su", 0x5a7}, 600 { "cvtts/su", 0x5ac}, 601 { "cvttq/sv", 0x5af}, 602 { "adds/sud", 0x5c0}, 603 { "subs/sud", 0x5c1}, 604 { "muls/sud", 0x5c2}, 605 { "divs/sud", 0x5c3}, 606 { "addt/sud", 0x5e0}, 607 { "subt/sud", 0x5e1}, 608 { "mult/sud", 0x5e2}, 609 { "divt/sud", 0x5e3}, 610 { "cvtts/sud", 0x5ec}, 611 { "adds/suic", 0x700}, 612 { "subs/suic", 0x701}, 613 { "muls/suic", 0x702}, 614 { "divs/suic", 0x703}, 615 { "addt/suic", 0x720}, 616 { "subt/suic", 0x721}, 617 { "mult/suic", 0x722}, 618 { "divt/suic", 0x723}, 619 { "cvtts/suic", 0x72c}, 620 { "cvttq/svic", 0x72f}, 621 { "cvtqs/suic", 0x73c}, 622 { "cvtqt/suic", 0x73e}, 623 { "adds/suim", 0x740}, 624 { "subs/suim", 0x741}, 625 { "muls/suim", 0x742}, 626 { "divs/suim", 0x743}, 627 { "addt/suim", 0x760}, 628 { "subt/suim", 0x761}, 629 { "mult/suim", 0x762}, 630 { "divt/suim", 0x763}, 631 { "cvtts/suim", 0x76c}, 632 { "cvtqs/suim", 0x77c}, 633 { "cvtqt/suim", 0x77e}, 634 { "adds/sui", 0x780}, 635 { "subs/sui", 0x781}, 636 { "muls/sui", 0x782}, 637 { "divs/sui", 0x783}, 638 { "addt/sui", 0x7a0}, 639 { "subt/sui", 0x7a1}, 640 { "mult/sui", 0x7a2}, 641 { "divt/sui", 0x7a3}, 642 { "cvtts/sui", 0x7ac}, 643 { "cvttq/svi", 0x7af}, 644 { "cvtqs/sui", 0x7bc}, 645 { "cvtqt/sui", 0x7be}, 646 { "adds/suid", 0x7c0}, 647 { "subs/suid", 0x7c1}, 648 { "muls/suid", 0x7c2}, 649 { "divs/suid", 0x7c3}, 650 { "addt/suid", 0x7e0}, 651 { "subt/suid", 0x7e1}, 652 { "mult/suid", 0x7e2}, 653 { "divt/suid", 0x7e3}, 654 { "cvtts/suid", 0x7ec}, 655 { "cvtqs/suid", 0x7fc}, 656 { "cvtqt/suid", 0x7fe}, 657 { 0, 0} 658 }; 659 660 static const struct tbl vaxf_tbl[] = { 661 { "addf/c", 0x000}, 662 { "subf/c", 0x001}, 663 { "mulf/c", 0x002}, 664 { "divf/c", 0x003}, 665 { "cvtdg/c", 0x01e}, 666 { "addg/c", 0x020}, 667 { "subg/c", 0x021}, 668 { "mulg/c", 0x022}, 669 { "divg/c", 0x023}, 670 { "cvtgf/c", 0x02c}, 671 { "cvtgd/c", 0x02d}, 672 { "cvtgq/c", 0x02f}, 673 { "cvtqf/c", 0x03c}, 674 { "cvtqg/c", 0x03e}, 675 { "addf", 0x080}, 676 { "subf", 0x081}, 677 { "mulf", 0x082}, 678 { "divf", 0x083}, 679 { "cvtdg", 0x09e}, 680 { "addg", 0x0a0}, 681 { "subg", 0x0a1}, 682 { "mulg", 0x0a2}, 683 { "divg", 0x0a3}, 684 { "cmpgeq", 0x0a5}, 685 { "cmpglt", 0x0a6}, 686 { "cmpgle", 0x0a7}, 687 { "cvtgf", 0x0ac}, 688 { "cvtgd", 0x0ad}, 689 { "cvtgq", 0x0af}, 690 { "cvtqf", 0x0bc}, 691 { "cvtqg", 0x0be}, 692 { "addf/uc", 0x100}, 693 { "subf/uc", 0x101}, 694 { "mulf/uc", 0x102}, 695 { "divf/uc", 0x103}, 696 { "cvtdg/uc", 0x11e}, 697 { "addg/uc", 0x120}, 698 { "subg/uc", 0x121}, 699 { "mulg/uc", 0x122}, 700 { "divg/uc", 0x123}, 701 { "cvtgf/uc", 0x12c}, 702 { "cvtgd/uc", 0x12d}, 703 { "cvtgq/vc", 0x12f}, 704 { "addf/u", 0x180}, 705 { "subf/u", 0x181}, 706 { "mulf/u", 0x182}, 707 { "divf/u", 0x183}, 708 { "cvtdg/u", 0x19e}, 709 { "addg/u", 0x1a0}, 710 { "subg/u", 0x1a1}, 711 { "mulg/u", 0x1a2}, 712 { "divg/u", 0x1a3}, 713 { "cvtgf/u", 0x1ac}, 714 { "cvtgd/u", 0x1ad}, 715 { "cvtgq/v", 0x1af}, 716 { "addf/sc", 0x400}, 717 { "subf/sc", 0x401}, 718 { "mulf/sc", 0x402}, 719 { "divf/sc", 0x403}, 720 { "cvtdg/sc", 0x41e}, 721 { "addg/sc", 0x420}, 722 { "subg/sc", 0x421}, 723 { "mulg/sc", 0x422}, 724 { "divg/sc", 0x423}, 725 { "cvtgf/sc", 0x42c}, 726 { "cvtgd/sc", 0x42d}, 727 { "cvtgq/sc", 0x42f}, 728 { "cvtqf/sc", 0x43c}, 729 { "cvtqg/sc", 0x43e}, 730 { "addf/s", 0x480}, 731 { "subf/s", 0x481}, 732 { "mulf/s", 0x482}, 733 { "divf/s", 0x483}, 734 { "cvtdg/s", 0x49e}, 735 { "addg/s", 0x4a0}, 736 { "subg/s", 0x4a1}, 737 { "mulg/s", 0x4a2}, 738 { "divg/s", 0x4a3}, 739 { "cmpgeq/s", 0x4a5}, 740 { "cmpglt/s", 0x4a6}, 741 { "cmpgle/s", 0x4a7}, 742 { "cvtgf/s", 0x4ac}, 743 { "cvtgd/s", 0x4ad}, 744 { "cvtgq/s", 0x4af}, 745 { "cvtqf/s", 0x4bc}, 746 { "cvtqg/s", 0x4be}, 747 { "addf/suc", 0x500}, 748 { "subf/suc", 0x501}, 749 { "mulf/suc", 0x502}, 750 { "divf/suc", 0x503}, 751 { "cvtdg/suc", 0x51e}, 752 { "addg/suc", 0x520}, 753 { "subg/suc", 0x521}, 754 { "mulg/suc", 0x522}, 755 { "divg/suc", 0x523}, 756 { "cvtgf/suc", 0x52c}, 757 { "cvtgd/suc", 0x52d}, 758 { "cvtgq/svc", 0x52f}, 759 { "addf/su", 0x580}, 760 { "subf/su", 0x581}, 761 { "mulf/su", 0x582}, 762 { "divf/su", 0x583}, 763 { "cvtdg/su", 0x59e}, 764 { "addg/su", 0x5a0}, 765 { "subg/su", 0x5a1}, 766 { "mulg/su", 0x5a2}, 767 { "divg/su", 0x5a3}, 768 { "cvtgf/su", 0x5ac}, 769 { "cvtgd/su", 0x5ad}, 770 { "cvtgq/sv", 0x5af}, 771 { 0, 0} 772 }; 773 774 /* 775 * General purpose registers 776 */ 777 static const char *name_of_register[32] = { 778 "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", 779 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", 780 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9", 781 "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero" 782 }; 783 784 static int regcount; /* how many regs used in this inst */ 785 static int regnum[3]; /* which regs used in this inst */ 786 787 static const char * 788 register_name(int ireg) 789 { 790 int i; 791 792 for (i = 0; i < regcount; i++) 793 if (regnum[i] == ireg) 794 break; 795 if (i >= regcount) 796 regnum[regcount++] = ireg; 797 return (name_of_register[ireg]); 798 } 799 800 /* 801 * Disassemble instruction at 'loc'. 'altfmt' specifies an 802 * (optional) alternate format. Return address of start of 803 * next instruction. 804 */ 805 806 static int 807 alpha_print_instruction(db_addr_t iadr, alpha_instruction i, 808 boolean_t showregs) 809 { 810 const char *opcode; 811 int ireg; 812 long signed_immediate; 813 boolean_t fstore; 814 pal_instruction p; 815 816 regcount = 0; 817 fstore = FALSE; 818 opcode = op_name[i.mem_format.opcode]; 819 820 /* 821 * Dispatch directly on the opcode, save code 822 * duplication sometimes via "harmless gotos". 823 */ 824 switch (i.mem_format.opcode) { 825 case op_pal: 826 /* "call_pal" is a long string; just use a space. */ 827 db_printf("%s %s", opcode, pal_opname(i.pal_format.function)); 828 break; 829 case op_lda: 830 case op_ldah: 831 case op_ldbu: 832 case op_ldq_u: 833 case op_ldwu: 834 case op_stw: 835 case op_stb: 836 case op_stq_u: 837 /* 838 * These loadstores are here to make compiling the 839 * switch a bit easier. Could embellish the output 840 * someday, too. 841 */ 842 goto loadstore; 843 break; 844 case op_arit: 845 /* 846 * For this and the following three groups we 847 * just need different opcode strings 848 */ 849 opcode = arit_name(i.operate_lit_format.function); 850 goto operate; 851 break; 852 case op_logical: 853 opcode = logical_name(i.operate_lit_format.function); 854 goto operate; 855 break; 856 case op_bit: 857 opcode = bitop_name(i.operate_lit_format.function); 858 goto operate; 859 break; 860 case op_mul: 861 opcode = mul_name(i.operate_lit_format.function); 862 operate: 863 /* 864 * Nice and uniform, just check for literals 865 */ 866 db_printf("%s\t%s,", opcode, 867 register_name(i.operate_lit_format.ra)); 868 if (i.operate_lit_format.one) 869 db_printf("#0x%x", i.operate_lit_format.literal); 870 else 871 db_printf("%s", register_name(i.operate_reg_format.rb)); 872 db_printf(",%s", register_name(i.operate_lit_format.rc)); 873 break; 874 case op_vax_float: 875 /* 876 * The three floating point groups are even simpler 877 */ 878 opcode = vaxf_name(i.float_format.function); 879 goto foperate; 880 break; 881 case op_ieee_float: 882 opcode = ieeef_name(i.float_format.function); 883 goto foperate; 884 break; 885 case op_any_float: 886 opcode = anyf_name(i.float_format.function); 887 foperate: 888 db_printf("%s\tf%d,f%d,f%d", opcode, 889 i.float_format.fa, 890 i.float_format.fb, 891 i.float_format.fc); 892 break; 893 case op_special: 894 /* 895 * Miscellaneous. 896 */ 897 { 898 register unsigned int code; 899 900 code = (i.mem_format.displacement)&0xffff; 901 opcode = special_name(code); 902 903 switch (code) { 904 case op_ecb: 905 db_printf("%s\t(%s)", opcode, 906 register_name(i.mem_format.rb)); 907 break; 908 case op_fetch: 909 case op_fetch_m: 910 db_printf("%s\t0(%s)", opcode, 911 register_name(i.mem_format.rb)); 912 break; 913 case op_rpcc: 914 case op_rc: 915 case op_rs: 916 db_printf("%s\t%s", opcode, 917 register_name(i.mem_format.ra)); 918 break; 919 default: 920 db_printf("%s", opcode); 921 break; 922 } 923 } 924 break; 925 case op_j: 926 /* 927 * Jump instructions really are of two sorts, 928 * depending on the use of the hint info. 929 */ 930 opcode = jump_name(i.jump_format.action); 931 switch (i.jump_format.action) { 932 case op_jmp: 933 case op_jsr: 934 db_printf("%s\t%s,(%s),", opcode, 935 register_name(i.jump_format.ra), 936 register_name(i.jump_format.rb)); 937 signed_immediate = i.jump_format.hint; 938 goto branch_displacement; 939 break; 940 case op_ret: 941 case op_jcr: 942 db_printf("%s\t%s,(%s)", opcode, 943 register_name(i.jump_format.ra), 944 register_name(i.jump_format.rb)); 945 break; 946 } 947 break; 948 case op_intmisc: 949 /* 950 * These are just in "operate" format. 951 */ 952 opcode = intmisc_name(i.operate_lit_format.function); 953 goto operate; 954 break; 955 /* HW instructions, possibly chip-specific XXXX */ 956 case op_pal19: /* "hw_mfpr" */ 957 case op_pal1d: /* "hw_mtpr" */ 958 p.bits = i.bits; 959 db_printf("\t%s%s\t%s, %d", opcode, 960 mXpr_name[p.mXpr_format.regset], 961 register_name(p.mXpr_format.rd), 962 p.mXpr_format.index); 963 break; 964 case op_pal1b: /* "hw_ld" */ 965 case op_pal1f: /* "hw_st" */ 966 p.bits = i.bits; 967 db_printf("\t%s%c%s\t%s,", opcode, 968 (p.mem_format.qw) ? 'q' : 'l', 969 hwlds_name[p.mem_format.qualif], 970 register_name(p.mem_format.rd)); 971 signed_immediate = (long)p.mem_format.displacement; 972 goto loadstore_address; 973 974 case op_pal1e: /* "hw_rei" */ 975 db_printf("\t%s", opcode); 976 break; 977 978 case op_ldf: 979 case op_ldg: 980 case op_lds: 981 case op_ldt: 982 case op_stf: 983 case op_stg: 984 case op_sts: 985 case op_stt: 986 fstore = TRUE; 987 /* fall through */ 988 case op_ldl: 989 case op_ldq: 990 case op_ldl_l: 991 case op_ldq_l: 992 case op_stl: 993 case op_stq: 994 case op_stl_c: 995 case op_stq_c: 996 /* 997 * Memory operations, including floats 998 */ 999 loadstore: 1000 if (fstore) 1001 db_printf("%s\tf%d,", opcode, i.mem_format.ra); 1002 else 1003 db_printf("%s\t%s,", opcode, 1004 register_name(i.mem_format.ra)); 1005 signed_immediate = (long)i.mem_format.displacement; 1006 loadstore_address: 1007 { 1008 char tbuf[24]; 1009 1010 db_format_hex(tbuf, 24, signed_immediate, FALSE); 1011 db_printf("%s(%s)", tbuf, 1012 register_name(i.mem_format.rb)); 1013 } 1014 /* 1015 * For convenience, do the address computation 1016 */ 1017 if (showregs) { 1018 if (i.mem_format.opcode == op_ldah) 1019 signed_immediate <<= 16; 1020 db_printf(" <0x%lx>", signed_immediate + 1021 db_register_value(DDB_REGS, i.mem_format.rb)); 1022 } 1023 break; 1024 case op_br: 1025 case op_fbeq: 1026 case op_fblt: 1027 case op_fble: 1028 case op_bsr: 1029 case op_fbne: 1030 case op_fbge: 1031 case op_fbgt: 1032 case op_blbc: 1033 case op_beq: 1034 case op_blt: 1035 case op_ble: 1036 case op_blbs: 1037 case op_bne: 1038 case op_bge: 1039 case op_bgt: 1040 /* 1041 * We want to know where we are branching to 1042 */ 1043 signed_immediate = (long)i.branch_format.displacement; 1044 db_printf("%s\t%s,", opcode, 1045 register_name(i.branch_format.ra)); 1046 branch_displacement: 1047 db_printsym(iadr + sizeof(alpha_instruction) + 1048 (signed_immediate << 2), DB_STGY_PROC, db_printf); 1049 break; 1050 default: 1051 /* 1052 * Shouldn't happen 1053 */ 1054 db_printf("? 0x%x ?", i.bits); 1055 } 1056 1057 /* 1058 * Print out the registers used in this instruction 1059 */ 1060 if (showregs && regcount > 0) { 1061 db_printf("\t<"); 1062 for (ireg = 0; ireg < regcount; ireg++) { 1063 if (ireg != 0) 1064 db_printf(","); 1065 db_printf("%s=0x%lx", 1066 name_of_register[regnum[ireg]], 1067 db_register_value(DDB_REGS, regnum[ireg])); 1068 } 1069 db_printf(">"); 1070 } 1071 db_printf("\n"); 1072 return (sizeof(alpha_instruction)); 1073 } 1074 1075 db_addr_t 1076 db_disasm(db_addr_t loc, boolean_t altfmt) 1077 { 1078 alpha_instruction inst; 1079 1080 inst.bits = db_get_value(loc, 4, 0); 1081 1082 loc += alpha_print_instruction(loc, inst, altfmt); 1083 return (loc); 1084 } 1085