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