1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 2009 Jason King. All rights reserved. 29 * Use is subject to license terms. 30 */ 31 32 33 #include <sys/byteorder.h> 34 #include <stdarg.h> 35 36 #if !defined(DIS_STANDALONE) 37 #include <stdio.h> 38 #endif /* DIS_STANDALONE */ 39 40 #include "libdisasm.h" 41 #include "libdisasm_impl.h" 42 #include "dis_sparc.h" 43 #include "dis_sparc_fmt.h" 44 45 extern char *strncpy(char *, const char *, size_t); 46 extern size_t strlen(const char *); 47 extern int strcmp(const char *, const char *); 48 extern int strncmp(const char *, const char *, size_t); 49 extern size_t strlcat(char *, const char *, size_t); 50 extern size_t strlcpy(char *, const char *, size_t); 51 extern int snprintf(char *, size_t, const char *, ...); 52 extern int vsnprintf(char *, size_t, const char *, va_list); 53 54 /* 55 * This file has the functions that do all the dirty work of outputting the 56 * disassembled instruction 57 * 58 * All the non-static functions follow the format_fcn (in dis_sparc.h): 59 * Input: 60 * disassembler handle/context 61 * instruction to disassemble 62 * instruction definition pointer (inst_t *) 63 * index in the table of the instruction 64 * Return: 65 * 0 Success 66 * !0 Invalid instruction 67 * 68 * Generally, instructions found in the same table use the same output format 69 * or have a few minor differences (which are described in the 'flags' field 70 * of the instruction definition. In some cases, certain instructions differ 71 * radically enough from those in the same table, that their own format 72 * function is used. 73 * 74 * Typically each table has a unique format function defined in this file. In 75 * some cases (such as branches) a common one for all the tables is used. 76 * 77 * When adding support for new instructions, it is largely a judgement call 78 * as to when a new format function is defined. 79 */ 80 81 /* The various instruction formats of a sparc instruction */ 82 83 #if defined(_BIT_FIELDS_HTOL) 84 typedef struct format1 { 85 uint32_t op:2; 86 uint32_t disp30:30; 87 } format1_t; 88 #elif defined(_BIT_FIELDS_LTOH) 89 typedef struct format1 { 90 uint32_t disp30:30; 91 uint32_t op:2; 92 } format1_t; 93 #else 94 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 95 #endif 96 97 #if defined(_BIT_FIELDS_HTOL) 98 typedef struct format2 { 99 uint32_t op:2; 100 uint32_t rd:5; 101 uint32_t op2:3; 102 uint32_t imm22:22; 103 } format2_t; 104 #elif defined(_BIT_FIELDS_LTOH) 105 typedef struct format2 { 106 uint32_t imm22:22; 107 uint32_t op2:3; 108 uint32_t rd:5; 109 uint32_t op:2; 110 } format2_t; 111 #else 112 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 113 #endif 114 115 #if defined(_BIT_FIELDS_HTOL) 116 typedef struct format2a { 117 uint32_t op:2; 118 uint32_t a:1; 119 uint32_t cond:4; 120 uint32_t op2:3; 121 uint32_t disp22:22; 122 } format2a_t; 123 #elif defined(_BIT_FIELDS_LTOH) 124 typedef struct format2a { 125 uint32_t disp22:22; 126 uint32_t op2:3; 127 uint32_t cond:4; 128 uint32_t a:1; 129 uint32_t op:2; 130 } format2a_t; 131 #else 132 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 133 #endif 134 135 #if defined(_BIT_FIELDS_HTOL) 136 typedef struct format2b { 137 uint32_t op:2; 138 uint32_t a:1; 139 uint32_t cond:4; 140 uint32_t op2:3; 141 uint32_t cc:2; 142 uint32_t p:1; 143 uint32_t disp19:19; 144 } format2b_t; 145 #elif defined(_BIT_FIELDS_LTOH) 146 typedef struct format2b { 147 uint32_t disp19:19; 148 uint32_t p:1; 149 uint32_t cc:2; 150 uint32_t op2:3; 151 uint32_t cond:4; 152 uint32_t a:1; 153 uint32_t op:2; 154 } format2b_t; 155 #else 156 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 157 #endif 158 159 #if defined(_BIT_FIELDS_HTOL) 160 typedef struct format2c { 161 uint32_t op:2; 162 uint32_t a:1; 163 uint32_t cond:4; 164 uint32_t op2:3; 165 uint32_t d16hi:2; 166 uint32_t p:1; 167 uint32_t rs1:5; 168 uint32_t d16lo:14; 169 } format2c_t; 170 #elif defined(_BIT_FIELDS_LTOH) 171 typedef struct format2c { 172 uint32_t d16lo:14; 173 uint32_t rs1:5; 174 uint32_t p:1; 175 uint32_t d16hi:2; 176 uint32_t op2:3; 177 uint32_t cond:4; 178 uint32_t a:1; 179 uint32_t op:2; 180 } format2c_t; 181 #else 182 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 183 #endif 184 185 #if defined(_BIT_FIELDS_HTOL) 186 typedef struct format3 { 187 uint32_t op:2; 188 uint32_t rd:5; 189 uint32_t op3:6; 190 uint32_t rs1:5; 191 uint32_t i:1; 192 uint32_t asi:8; 193 uint32_t rs2:5; 194 } format3_t; 195 #elif defined(_BIT_FIELDS_LTOH) 196 typedef struct format3 { 197 uint32_t rs2:5; 198 uint32_t asi:8; 199 uint32_t i:1; 200 uint32_t rs1:5; 201 uint32_t op3:6; 202 uint32_t rd:5; 203 uint32_t op:2; 204 } format3_t; 205 #else 206 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 207 #endif 208 209 #if defined(_BIT_FIELDS_HTOL) 210 typedef struct format3a { 211 uint32_t op:2; 212 uint32_t rd:5; 213 uint32_t op3:6; 214 uint32_t rs1:5; 215 uint32_t i:1; 216 uint32_t simm13:13; 217 } format3a_t; 218 #elif defined(_BIT_FIELDS_LTOH) 219 typedef struct format3a { 220 uint32_t simm13:13; 221 uint32_t i:1; 222 uint32_t rs1:5; 223 uint32_t op3:6; 224 uint32_t rd:5; 225 uint32_t op:2; 226 } format3a_t; 227 #else 228 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 229 #endif 230 231 #if defined(_BIT_FIELDS_HTOL) 232 typedef struct format3b { 233 uint32_t op:2; 234 uint32_t rd:5; 235 uint32_t op3:6; 236 uint32_t rs1:5; 237 uint32_t i:1; 238 uint32_t x:1; 239 uint32_t undef:6; 240 uint32_t shcnt:6; 241 } format3b_t; 242 #elif defined(_BIT_FIELDS_LTOH) 243 typedef struct format3b { 244 uint32_t shcnt:6; 245 uint32_t undef:6; 246 uint32_t x:1; 247 uint32_t i:1; 248 uint32_t rs1:5; 249 uint32_t op3:6; 250 uint32_t rd:5; 251 uint32_t op:2; 252 } format3b_t; 253 #else 254 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 255 #endif 256 257 #if defined(_BIT_FIELDS_HTOL) 258 typedef struct format3c { 259 uint32_t op:2; 260 uint32_t rd:5; 261 uint32_t op3:6; 262 uint32_t cc2:1; 263 uint32_t cond:4; 264 uint32_t i:1; 265 uint32_t cc:2; 266 uint32_t simm11:11; 267 } format3c_t; 268 #elif defined(_BIT_FIELDS_LTOH) 269 typedef struct format3c { 270 uint32_t simm11:11; 271 uint32_t cc:2; 272 uint32_t i:1; 273 uint32_t cond:4; 274 uint32_t cc2:1; 275 uint32_t op3:6; 276 uint32_t rd:5; 277 uint32_t op:2; 278 } format3c_t; 279 #else 280 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 281 #endif 282 283 #if defined(_BIT_FIELDS_HTOL) 284 typedef struct format3d { 285 uint32_t op:2; 286 uint32_t rd:5; 287 uint32_t op3:6; 288 uint32_t rs1:5; 289 uint32_t i:1; 290 uint32_t rcond:3; 291 uint32_t simm10:10; 292 } format3d_t; 293 #elif defined(_BIT_FIELDS_LTOH) 294 typedef struct format3d { 295 uint32_t simm10:10; 296 uint32_t rcond:3; 297 uint32_t i:1; 298 uint32_t rs1:5; 299 uint32_t op3:6; 300 uint32_t rd:5; 301 uint32_t op:2; 302 } format3d_t; 303 #else 304 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 305 #endif 306 307 #if defined(_BIT_FIELDS_HTOL) 308 typedef struct formatcp { 309 uint32_t op:2; 310 uint32_t rd:5; 311 uint32_t op3:6; 312 uint32_t rs1:5; 313 uint32_t opc:9; 314 uint32_t rs2:5; 315 } formatcp_t; 316 #elif defined(_BIT_FIELDS_LTOH) 317 typedef struct formatcp { 318 uint32_t rs2:5; 319 uint32_t opc:9; 320 uint32_t rs1:5; 321 uint32_t op3:6; 322 uint32_t rd:5; 323 uint32_t op:2; 324 } formatcp_t; 325 #else 326 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 327 #endif 328 329 #if defined(_BIT_FIELDS_HTOL) 330 typedef struct formattcc { 331 uint32_t op:2; 332 uint32_t undef:1; 333 uint32_t cond:4; 334 uint32_t op3:6; 335 uint32_t rs1:5; 336 uint32_t i:1; 337 uint32_t cc:2; 338 uint32_t undef2:3; 339 uint32_t immtrap:8; 340 } formattcc_t; 341 #elif defined(_BIT_FIELDS_LTOH) 342 typedef struct formattcc { 343 uint32_t immtrap:8; 344 uint32_t undef2:3; 345 uint32_t cc:2; 346 uint32_t i:1; 347 uint32_t rs1:5; 348 uint32_t op3:6; 349 uint32_t cond:4; 350 uint32_t undef:1; 351 uint32_t op:2; 352 } formattcc_t; 353 #else 354 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 355 #endif 356 357 #if defined(_BIT_FIELDS_HTOL) 358 typedef struct formattcc2 { 359 uint32_t op:2; 360 uint32_t undef:1; 361 uint32_t cond:4; 362 uint32_t op3:6; 363 uint32_t rs1:5; 364 uint32_t i:1; 365 uint32_t cc:2; 366 uint32_t undef2:6; 367 uint32_t rs2:5; 368 } formattcc2_t; 369 #elif defined(_BIT_FIELDS_LTOH) 370 typedef struct formattcc2 { 371 uint32_t rs2:5; 372 uint32_t undef2:6; 373 uint32_t cc:2; 374 uint32_t i:1; 375 uint32_t rs1:5; 376 uint32_t op3:6; 377 uint32_t cond:4; 378 uint32_t undef:1; 379 uint32_t op:2; 380 } formattcc2_t; 381 #else 382 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 383 #endif 384 385 #if defined(_BIT_FIELDS_HTOL) 386 typedef struct formatmbr { 387 uint32_t op:2; 388 uint32_t rd:5; 389 uint32_t op3:6; 390 uint32_t rs1:5; 391 uint32_t i:1; 392 uint32_t undef:6; 393 uint32_t cmask:3; 394 uint32_t mmask:4; 395 } formatmbr_t; 396 #elif defined(_BIT_FIELDS_LTOH) 397 typedef struct formatmbr { 398 uint32_t mmask:4; 399 uint32_t cmask:3; 400 uint32_t undef:6; 401 uint32_t i:1; 402 uint32_t rs1:5; 403 uint32_t op3:6; 404 uint32_t rd:5; 405 uint32_t op:2; 406 } formatmbr_t; 407 #else 408 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 409 #endif 410 411 #if defined(_BIT_FIELDS_HTOL) 412 typedef struct formatfcmp { 413 uint32_t op:2; 414 uint32_t undef:3; 415 uint32_t cc:2; 416 uint32_t op3:6; 417 uint32_t rs1:5; 418 uint32_t opf:9; 419 uint32_t rs2:5; 420 } formatfcmp_t; 421 #elif defined(_BIT_FIELDS_LTOH) 422 typedef struct formatfcmp { 423 uint32_t rs2:5; 424 uint32_t opf:9; 425 uint32_t rs1:5; 426 uint32_t op3:6; 427 uint32_t cc:2; 428 uint32_t undef:3; 429 uint32_t op:2; 430 } formatfcmp_t; 431 #else 432 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 433 #endif 434 435 #if defined(_BIT_FIELDS_HTOL) 436 typedef struct formatfmov { 437 uint32_t op:2; 438 uint32_t rd:5; 439 uint32_t op3:6; 440 uint32_t undef:1; 441 uint32_t cond:4; 442 uint32_t cc:3; 443 uint32_t opf:6; 444 uint32_t rs2:5; 445 } formatfmov_t; 446 #elif defined(_BIT_FIELDS_LTOH) 447 typedef struct formatfmov { 448 uint32_t rs2:5; 449 uint32_t opf:6; 450 uint32_t cc:3; 451 uint32_t cond:4; 452 uint32_t undef:1; 453 uint32_t op3:6; 454 uint32_t rd:5; 455 uint32_t op:2; 456 } formatfmov_t; 457 #else 458 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 459 #endif 460 461 #if defined(_BIT_FIELDS_HTOL) 462 typedef struct formatfused { 463 uint32_t op:2; 464 uint32_t rd:5; 465 uint32_t op3:6; 466 uint32_t rs1:5; 467 uint32_t rs3:5; 468 uint32_t op5:4; 469 uint32_t rs2:5; 470 } formatfused_t; 471 #elif defined(_BIT_FIELDS_LTOH) 472 typedef struct formatfused { 473 uint32_t rs2:5; 474 uint32_t op5:4; 475 uint32_t rs3:5; 476 uint32_t rs1:5; 477 uint32_t op3:6; 478 uint32_t rd:5; 479 uint32_t op:2; 480 } formatfused_t; 481 #else 482 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 483 #endif 484 485 typedef union ifmt { 486 uint32_t i; 487 format1_t f1; 488 format2_t f2; 489 format2a_t f2a; 490 format2b_t f2b; 491 format2c_t f2c; 492 format3_t f3; 493 format3a_t f3a; 494 format3b_t f3b; 495 format3c_t f3c; 496 format3d_t f3d; 497 formatcp_t fcp; 498 formattcc_t ftcc; 499 formattcc2_t ftcc2; 500 formatfcmp_t fcmp; 501 formatmbr_t fmb; 502 formatfmov_t fmv; 503 formatfused_t fused; 504 } ifmt_t; 505 506 /* integer register names */ 507 static const char *reg_names[32] = { 508 "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7", 509 "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7", 510 "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", 511 "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7" 512 }; 513 514 /* floating point register names */ 515 static const char *freg_names[32] = { 516 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", 517 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15", 518 "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23", 519 "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31" 520 }; 521 522 /* double precision register names */ 523 static const char *fdreg_names[32] = { 524 "%d0", "%d32", "%d2", "%d34", "%d4", "%d36", "%d6", "%d38", 525 "%d8", "%d40", "%d10", "%d42", "%d12", "%d44", "%d14", "%d46", 526 "%d16", "%d48", "%d18", "%d50", "%d20", "%d52", "%d22", "%d54", 527 "%d24", "%d56", "%d26", "%d58", "%d28", "%d60", "%d30", "%d62" 528 }; 529 530 static const char *compat_fdreg_names[32] = { 531 "%f0", "%f32", "%f2", "%f34", "%f4", "%f36", "%f6", "%f38", 532 "%f8", "%f40", "%f10", "%f42", "%f12", "%f44", "%f14", "%f46", 533 "%f16", "%f48", "%f18", "%f50", "%f20", "%f52", "%f22", "%f54", 534 "%f24", "%f56", "%f26", "%f58", "%f28", "%f60", "%f30", "%f62" 535 }; 536 537 538 static const char *fqreg_names[32] = { 539 "%q0", "%q32", "%f2", "%f3", "%f4", "%q4", "%q36", "%f6", 540 "%f7", "%q8", "%q40", "%f10", "%f11", "%q12", "%q44", "%f14", 541 "%f15", "%q16", "%q48", "%f18", "%f19", "%q20", "%q52", "%f22", 542 "%f23", "%q24", "%q56", "%f26", "%f27", "%q28", "%q60", "%f30", 543 }; 544 545 546 /* coprocessor register names -- sparcv8 only */ 547 static const char *cpreg_names[32] = { 548 "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7", 549 "%c8", "%c9", "%c10", "%c11", "%c12", "%c13", "%c14", "%c15", 550 "%c16", "%c17", "%c18", "%c19", "%c20", "%c21", "%c22", "%c23", 551 "%c24", "%c25", "%c26", "%c27", "%c28", "%c29", "%c30", "%c31", 552 }; 553 554 /* floating point condition code names */ 555 static const char *fcc_names[4] = { 556 "%fcc0", "%fcc1", "%fcc2", "%fcc3" 557 }; 558 559 /* condition code names */ 560 static const char *icc_names[4] = { 561 "%icc", NULL, "%xcc", NULL 562 }; 563 564 /* bitmask values for membar */ 565 static const char *membar_mmask[4] = { 566 "#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore" 567 }; 568 569 static const char *membar_cmask[3] = { 570 "#Lookaside", "#MemIssue", "#Sync" 571 }; 572 573 /* v8 ancillary state register names */ 574 static const char *asr_names[32] = { 575 "%y", "%asr1", "%asr2", "%asr3", 576 "%asr4", "%asr5", "%asr6", "%asr7", 577 "%asr8", "%asr9", "%asr10", "%asr11", 578 "%asr12", "%asr13", "%asr14", "%asr15", 579 NULL, NULL, NULL, NULL, 580 NULL, NULL, NULL, NULL, 581 NULL, NULL, NULL, NULL, 582 NULL, NULL, NULL, NULL 583 }; 584 static const uint32_t asr_rdmask = 0x0000ffffL; 585 static const uint32_t asr_wrmask = 0x0000ffffL; 586 587 static const char *v9_asr_names[32] = { 588 "%y", NULL, "%ccr", "%asi", 589 "%tick", "%pc", "%fprs", NULL, 590 NULL, NULL, NULL, NULL, 591 NULL, NULL, NULL, NULL, 592 "%pcr", "%pic", "%dcr", "%gsr", 593 "%softint_set", "%softint_clr", "%softint", "%tick_cmpr", 594 "%stick", "%stick_cmpr", NULL, NULL, 595 NULL, NULL, NULL, NULL 596 }; 597 /* 598 * on v9, only certain registers are valid for read or writing 599 * these are bitmasks corresponding to which registers are valid in which 600 * case. Any access to %dcr is illegal. 601 */ 602 static const uint32_t v9_asr_rdmask = 0x03cb007d; 603 static const uint32_t v9_asr_wrmask = 0x03fb004d; 604 605 /* privledged register names on v9 */ 606 /* TODO: compat - NULL to %priv_nn */ 607 static const char *v9_privreg_names[32] = { 608 "%tpc", "%tnpc", "%tstate", "%tt", 609 "%tick", "%tba", "%pstate", "%tl", 610 "%pil", "%cwp", "%cansave", "%canrestore", 611 "%cleanwin", "%otherwin", "%wstate", "%fq", 612 "%gl", NULL, NULL, NULL, 613 NULL, NULL, NULL, NULL, 614 NULL, NULL, NULL, NULL, 615 NULL, NULL, NULL, "%ver" 616 }; 617 618 /* hyper privileged register names on v9 */ 619 static const char *v9_hprivreg_names[32] = { 620 "%hpstate", "%htstate", NULL, "%hintp", 621 NULL, "%htba", "%hver", NULL, 622 NULL, NULL, NULL, NULL, 623 NULL, NULL, NULL, NULL, 624 NULL, NULL, NULL, NULL, 625 NULL, NULL, NULL, NULL, 626 NULL, NULL, NULL, NULL, 627 NULL, NULL, NULL, "%hstick_cmpr" 628 }; 629 630 static const uint32_t v9_pr_rdmask = 0x80017fff; 631 static const uint32_t v9_pr_wrmask = 0x00017fff; 632 static const uint32_t v9_hpr_rdmask = 0x8000006b; 633 static const uint32_t v9_hpr_wrmask = 0x8000006b; 634 635 static const char *prefetch_str[32] = { 636 "#n_reads", "#one_read", 637 "#n_writes", "#one_write", 638 "#page", NULL, NULL, NULL, 639 NULL, NULL, NULL, NULL, 640 NULL, NULL, NULL, NULL, 641 NULL, "#unified", NULL, NULL, 642 "#n_reads_strong", "#one_read_strong", 643 "#n_writes_strong", "#one_write_strong", 644 NULL, NULL, NULL, NULL, 645 NULL, NULL, NULL, NULL 646 }; 647 648 static void prt_field(const char *, uint32_t, int); 649 650 static const char *get_regname(dis_handle_t *, int, uint32_t); 651 static int32_t sign_extend(int32_t, int32_t); 652 653 static void prt_name(dis_handle_t *, const char *, int); 654 655 #define IMM_SIGNED 0x01 /* Is immediate value signed */ 656 #define IMM_ADDR 0x02 /* Is immediate value part of an address */ 657 static void prt_imm(dis_handle_t *, uint32_t, int); 658 659 static void prt_asi(dis_handle_t *, uint32_t); 660 static const char *get_asi_name(uint8_t); 661 static void prt_address(dis_handle_t *, uint32_t, int); 662 static void prt_aluargs(dis_handle_t *, uint32_t, uint32_t); 663 static void bprintf(dis_handle_t *, const char *, ...); 664 665 /* 666 * print out val (which is 'bitlen' bits long) in binary 667 */ 668 #if defined(DIS_STANDALONE) 669 /* ARGSUSED */ 670 void 671 prt_binary(uint32_t val, int bitlen) 672 { 673 674 } 675 676 #else 677 678 void 679 prt_binary(uint32_t val, int bitlen) 680 { 681 int i; 682 683 for (i = bitlen - 1; i >= 0; --i) { 684 (void) fprintf(stderr, ((val & (1L << i)) != 0) ? "1" : "0"); 685 686 if (i % 4 == 0 && i != 0) 687 (void) fprintf(stderr, " "); 688 } 689 } 690 #endif /* DIS_STANDALONE */ 691 692 693 /* 694 * print out a call instruction 695 * format: call address <name> 696 */ 697 /* ARGSUSED1 */ 698 int 699 fmt_call(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 700 { 701 ifmt_t *f = (ifmt_t *)&instr; 702 703 int32_t disp; 704 size_t curlen; 705 706 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0); 707 708 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 709 prt_field("op", f->f1.op, 2); 710 prt_field("disp30", f->f1.disp30, 30); 711 } 712 713 disp = sign_extend(f->f1.disp30, 30) * 4; 714 715 prt_name(dhp, inp->in_data.in_def.in_name, 1); 716 717 bprintf(dhp, (octal != 0) ? "%s0%-11lo" : "%s0x%-10lx", 718 (disp < 0) ? "-" : "+", 719 (disp < 0) ? (-disp) : disp); 720 721 (void) strlcat(dhp->dh_buf, " <", dhp->dh_buflen); 722 723 curlen = strlen(dhp->dh_buf); 724 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp, 725 dhp->dh_buf + curlen, dhp->dh_buflen - curlen - 1, NULL, 726 NULL); 727 (void) strlcat(dhp->dh_buf, ">", dhp->dh_buflen); 728 729 730 return (0); 731 } 732 733 int 734 fmt_sethi(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 735 { 736 ifmt_t *f = (ifmt_t *)&instr; 737 738 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 739 prt_field("op", f->f2.op, 2); 740 prt_field("op2", f->f2.op2, 3); 741 prt_field("rd", f->f2.rd, 5); 742 prt_field("imm22", f->f2.imm22, 22); 743 } 744 745 if (idx == 0) { 746 /* unimp / illtrap */ 747 prt_name(dhp, inp->in_data.in_def.in_name, 1); 748 prt_imm(dhp, f->f2.imm22, 0); 749 return (0); 750 } 751 752 if (f->f2.imm22 == 0 && f->f2.rd == 0) { 753 prt_name(dhp, "nop", 0); 754 return (0); 755 } 756 757 /* ?? Should we return -1 if rd == 0 && disp != 0 */ 758 759 prt_name(dhp, inp->in_data.in_def.in_name, 1); 760 761 bprintf(dhp, 762 ((dhp->dh_flags & DIS_OCTAL) != 0) ? 763 "%%hi(0%lo), %s" : "%%hi(0x%lx), %s", 764 f->f2.imm22 << 10, 765 reg_names[f->f2.rd]); 766 767 return (0); 768 } 769 770 /* ARGSUSED3 */ 771 int 772 fmt_branch(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 773 { 774 const char *name = inp->in_data.in_def.in_name; 775 const char *r = NULL; 776 const char *annul = ""; 777 const char *pred = ""; 778 779 char buf[15]; 780 781 ifmt_t *f = (ifmt_t *)&instr; 782 783 size_t curlen; 784 int32_t disp; 785 uint32_t flags = inp->in_data.in_def.in_flags; 786 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0); 787 788 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 789 prt_field("op", f->f2.op, 2); 790 prt_field("op2", f->f2.op2, 3); 791 792 switch (FLG_DISP_VAL(flags)) { 793 case DISP22: 794 prt_field("cond", f->f2a.cond, 4); 795 prt_field("a", f->f2a.a, 1); 796 prt_field("disp22", f->f2a.disp22, 22); 797 break; 798 799 case DISP19: 800 prt_field("cond", f->f2a.cond, 4); 801 prt_field("a", f->f2a.a, 1); 802 prt_field("p", f->f2b.p, 1); 803 prt_field("cc", f->f2b.cc, 2); 804 prt_field("disp19", f->f2b.disp19, 19); 805 break; 806 807 case DISP16: 808 prt_field("bit 28", ((instr & (1L << 28)) >> 28), 1); 809 prt_field("rcond", f->f2c.cond, 3); 810 prt_field("p", f->f2c.p, 1); 811 prt_field("rs1", f->f2c.rs1, 5); 812 prt_field("d16hi", f->f2c.d16hi, 2); 813 prt_field("d16lo", f->f2c.d16lo, 14); 814 break; 815 } 816 } 817 818 if (f->f2b.op2 == 0x01 && idx == 0x00 && f->f2b.p == 1 && 819 f->f2b.cc == 0x02 && ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) != 0)) { 820 name = "iprefetch"; 821 flags = FLG_RS1(REG_NONE)|FLG_DISP(DISP19); 822 } 823 824 825 switch (FLG_DISP_VAL(flags)) { 826 case DISP22: 827 disp = sign_extend(f->f2a.disp22, 22); 828 break; 829 830 case DISP19: 831 disp = sign_extend(f->f2b.disp19, 19); 832 break; 833 834 case DISP16: 835 disp = sign_extend((f->f2c.d16hi << 14)|f->f2c.d16lo, 16); 836 break; 837 838 } 839 840 disp *= 4; 841 842 if ((FLG_RS1_VAL(flags) == REG_ICC) || (FLG_RS1_VAL(flags) == REG_FCC)) 843 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2b.cc); 844 else 845 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2c.rs1); 846 847 if (r == NULL) 848 return (-1); 849 850 if (f->f2a.a == 1) 851 annul = ",a"; 852 853 if ((flags & FLG_PRED) != 0) { 854 if (f->f2b.p == 0) { 855 pred = ",pn"; 856 } else { 857 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0) 858 pred = ",pt"; 859 } 860 } 861 862 (void) snprintf(buf, sizeof (buf), "%s%s%s", name, annul, pred); 863 prt_name(dhp, buf, 1); 864 865 866 switch (FLG_DISP_VAL(flags)) { 867 case DISP22: 868 bprintf(dhp, 869 (octal != 0) ? "%s0%-11lo <" : "%s0x%-10lx <", 870 (disp < 0) ? "-" : "+", 871 (disp < 0) ? (-disp) : disp); 872 break; 873 874 case DISP19: 875 bprintf(dhp, 876 (octal != 0) ? "%s, %s0%-5lo <" : 877 "%s, %s0x%-04lx <", r, 878 (disp < 0) ? "-" : "+", 879 (disp < 0) ? (-disp) : disp); 880 break; 881 882 case DISP16: 883 bprintf(dhp, 884 (octal != 0) ? "%s, %s0%-6lo <" : "%s, %s0x%-5lx <", 885 r, 886 (disp < 0) ? "-" : "+", 887 (disp < 0) ? (-disp) : disp); 888 break; 889 } 890 891 curlen = strlen(dhp->dh_buf); 892 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp, 893 dhp->dh_buf + curlen, dhp->dh_buflen - curlen - 1, NULL, NULL); 894 895 (void) strlcat(dhp->dh_buf, ">", dhp->dh_buflen); 896 897 return (0); 898 } 899 900 901 902 /* 903 * print out the compare and swap instructions (casa/casxa) 904 * format: casa/casxa [%rs1] imm_asi, %rs2, %rd 905 * casa/casxa [%rs1] %asi, %rs2, %rd 906 * 907 * If DIS_DEBUG_SYN_ALL is set, synthetic instructions are emitted 908 * when an immediate ASI value is given as follows: 909 * 910 * casa [%rs1]#ASI_P, %rs2, %rd -> cas [%rs1], %rs2, %rd 911 * casa [%rs1]#ASI_P_L, %rs2, %rd -> casl [%rs1], %rs2, %rd 912 * casxa [%rs1]#ASI_P, %rs2, %rd -> casx [%rs1], %rs2, %rd 913 * casxa [%rs1]#ASI_P_L, %rs2, %rd -> casxl [%rs1], %rs2, %rd 914 */ 915 static int 916 fmt_cas(dis_handle_t *dhp, uint32_t instr, const char *name) 917 { 918 ifmt_t *f = (ifmt_t *)&instr; 919 const char *asistr = NULL; 920 int noasi = 0; 921 922 asistr = get_asi_name(f->f3.asi); 923 924 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) != 0) { 925 if (f->f3.op3 == 0x3c && f->f3.i == 0) { 926 if (f->f3.asi == 0x80) { 927 noasi = 1; 928 name = "cas"; 929 } 930 931 if (f->f3.asi == 0x88) { 932 noasi = 1; 933 name = "casl"; 934 } 935 } 936 937 if (f->f3.op3 == 0x3e && f->f3.i == 0) { 938 if (f->f3.asi == 0x80) { 939 noasi = 1; 940 name = "casx"; 941 } 942 943 if (f->f3.asi == 0x88) { 944 noasi = 1; 945 name = "casxl"; 946 } 947 } 948 } 949 950 prt_name(dhp, name, 1); 951 952 bprintf(dhp, "[%s]", reg_names[f->f3.rs1]); 953 954 if (noasi == 0) { 955 (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen); 956 prt_asi(dhp, instr); 957 } 958 959 bprintf(dhp, ", %s, %s", reg_names[f->f3.rs2], reg_names[f->f3.rd]); 960 961 if (noasi == 0 && asistr != NULL) 962 bprintf(dhp, "\t<%s>", asistr); 963 964 return (0); 965 } 966 967 /* 968 * format a load/store instruction 969 * format: ldXX [%rs1 + %rs2], %rd load, i==0 970 * ldXX [%rs1 +/- nn], %rd load, i==1 971 * ldXX [%rs1 + %rs2] #XX, %rd load w/ imm_asi, i==0 972 * ldXX [%rs1 +/- nn] %asi, %rd load from asi[%asi], i==1 973 * 974 * stXX %rd, [%rs1 + %rs2] store, i==0 975 * stXX %rd, [%rs1 +/- nn] store, i==1 976 * stXX %rd, [%rs1 + %rs1] #XX store to imm_asi, i==0 977 * stXX %rd, [%rs1 +/-nn] %asi store to asi[%asi], i==1 978 * 979 * The register sets used for %rd are set in the instructions flags field 980 * The asi variants are used if FLG_ASI is set in the instructions flags field 981 * 982 * If DIS_DEBUG_SYNTH_ALL or DIS_DEBUG_COMPAT are set, 983 * When %rs1, %rs2 or nn are 0, they are not printed, i.e. 984 * [ %rs1 + 0x0 ], %rd -> [%rs1], %rd for example 985 * 986 * The following synthetic instructions are also implemented: 987 * 988 * stb %g0, [addr] -> clrb [addr] DIS_DEBUG_SYNTH_ALL 989 * sth %g0, [addr] -> crlh [addr] DIS_DEBUG_SYNTH_ALL 990 * stw %g0, [addr] -> clr [addr] DIS_DEBUG_SYNTH_ALL|DIS_DEBUG_COMPAT 991 * stx %g0, [addr] -> clrx [addr] DIS_DEBUG_SYNTH_ALL 992 * 993 * If DIS_DEBUG_COMPAT is set, the following substitutions also take place 994 * lduw -> ld 995 * ldtw -> ld 996 * stuw -> st 997 * sttw -> st 998 */ 999 int 1000 fmt_ls(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1001 { 1002 ifmt_t *f = (ifmt_t *)&instr; 1003 const char *regstr = NULL; 1004 const char *asistr = NULL; 1005 1006 const char *iname = inp->in_data.in_def.in_name; 1007 uint32_t flags = inp->in_data.in_def.in_flags; 1008 1009 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 1010 prt_field("op", f->f3.op, 2); 1011 prt_field("op3", f->f3.op3, 6); 1012 prt_field("rs1", f->f3.rs1, 5); 1013 prt_field("i", f->f3.i, 1); 1014 if (f->f3.i != 0) { 1015 prt_field("simm13", f->f3a.simm13, 13); 1016 } else { 1017 if ((flags & FLG_ASI) != 0) 1018 prt_field("imm_asi", f->f3.asi, 8); 1019 prt_field("rs2", f->f3.rs2, 5); 1020 } 1021 prt_field("rd", f->f3.rd, 5); 1022 } 1023 1024 if (idx == 0x2d || idx == 0x3d) { 1025 /* prefetch / prefetcha */ 1026 1027 prt_name(dhp, iname, 1); 1028 1029 prt_address(dhp, instr, 0); 1030 1031 if (idx == 0x3d) { 1032 (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen); 1033 prt_asi(dhp, instr); 1034 } 1035 1036 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 1037 1038 /* fcn field is the same as rd */ 1039 if (prefetch_str[f->f3.rd] != NULL) 1040 (void) strlcat(dhp->dh_buf, prefetch_str[f->f3.rd], 1041 dhp->dh_buflen); 1042 else 1043 prt_imm(dhp, f->f3.rd, 0); 1044 1045 if (idx == 0x3d && f->f3.i == 0) { 1046 asistr = get_asi_name(f->f3.asi); 1047 if (asistr != NULL) 1048 bprintf(dhp, "\t<%s>", asistr); 1049 } 1050 1051 return (0); 1052 } 1053 1054 /* casa / casxa */ 1055 if (idx == 0x3c || idx == 0x3e) 1056 return (fmt_cas(dhp, instr, iname)); 1057 1058 /* synthetic instructions & special cases */ 1059 switch (idx) { 1060 case 0x00: 1061 /* ld */ 1062 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) 1063 iname = "lduw"; 1064 break; 1065 1066 case 0x03: 1067 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) 1068 iname = "ldtw"; 1069 break; 1070 1071 case 0x04: 1072 /* stw */ 1073 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) 1074 iname = "stuw"; 1075 1076 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1077 == 0) 1078 break; 1079 1080 if (f->f3.rd == 0) { 1081 iname = "clr"; 1082 flags = FLG_RD(REG_NONE); 1083 } 1084 break; 1085 1086 case 0x05: 1087 /* stb */ 1088 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1089 == 0) 1090 break; 1091 1092 if (f->f3.rd == 0) { 1093 iname = "clrb"; 1094 flags = FLG_RD(REG_NONE); 1095 } 1096 break; 1097 1098 case 0x06: 1099 /* sth */ 1100 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1101 == 0) 1102 break; 1103 1104 if (f->f3.rd == 0) { 1105 iname = "clrh"; 1106 flags = FLG_RD(REG_NONE); 1107 } 1108 break; 1109 1110 case 0x07: 1111 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) 1112 iname = "sttw"; 1113 break; 1114 1115 case 0x0e: 1116 /* stx */ 1117 1118 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1119 == 0) 1120 break; 1121 1122 if (f->f3.rd == 0) { 1123 iname = "clrx"; 1124 flags = FLG_RD(REG_NONE); 1125 } 1126 break; 1127 1128 case 0x13: 1129 /* ldtwa */ 1130 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) && 1131 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0)) 1132 iname = "ldtwa"; 1133 break; 1134 1135 case 0x17: 1136 /* sttwa */ 1137 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) && 1138 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0)) 1139 iname = "sttwa"; 1140 break; 1141 1142 case 0x21: 1143 case 0x25: 1144 /* 1145 * on sparcv8 it merely says that rd != 1 should generate an 1146 * exception, on v9, it is illegal 1147 */ 1148 if ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0) 1149 break; 1150 1151 iname = (idx == 0x21) ? "ldx" : "stx"; 1152 1153 if (f->f3.rd > 1) 1154 return (-1); 1155 1156 break; 1157 1158 case 0x31: 1159 /* stda */ 1160 switch (f->f3.asi) { 1161 case 0xc0: 1162 case 0xc1: 1163 case 0xc8: 1164 case 0xc9: 1165 case 0xc2: 1166 case 0xc3: 1167 case 0xca: 1168 case 0xcb: 1169 case 0xc4: 1170 case 0xc5: 1171 case 0xcc: 1172 case 0xcd: 1173 /* 1174 * store partial floating point, only valid w/ 1175 * vis 1176 * 1177 * Somewhat confusingly, it uses the same op 1178 * code as 'stda' -- store double to alternate 1179 * space. It is distinguised by specific 1180 * imm_asi values (as seen above), and 1181 * has a slightly different output syntax 1182 */ 1183 1184 if ((dhp->dh_flags & DIS_SPARC_V9_SGI) == 0) 1185 break; 1186 if (f->f3.i != 0) 1187 break; 1188 prt_name(dhp, iname, 1); 1189 bprintf(dhp, "%s, %s, [%s] ", 1190 get_regname(dhp, REG_FPD, f->f3.rd), 1191 get_regname(dhp, REG_FPD, f->f3.rs2), 1192 get_regname(dhp, REG_FPD, f->f3.rs1)); 1193 prt_asi(dhp, instr); 1194 asistr = get_asi_name(f->f3.asi); 1195 if (asistr != NULL) 1196 bprintf(dhp, "\t<%s>", asistr); 1197 1198 return (0); 1199 1200 default: 1201 break; 1202 } 1203 1204 } 1205 1206 regstr = get_regname(dhp, FLG_RD_VAL(flags), f->f3.rd); 1207 1208 if (f->f3.i == 0) 1209 asistr = get_asi_name(f->f3.asi); 1210 1211 prt_name(dhp, iname, 1); 1212 1213 if ((flags & FLG_STORE) != 0) { 1214 if (regstr[0] != '\0') { 1215 (void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen); 1216 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 1217 } 1218 1219 prt_address(dhp, instr, 0); 1220 if ((flags & FLG_ASI) != 0) { 1221 (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen); 1222 prt_asi(dhp, instr); 1223 } 1224 } else { 1225 prt_address(dhp, instr, 0); 1226 if ((flags & FLG_ASI) != 0) { 1227 (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen); 1228 prt_asi(dhp, instr); 1229 } 1230 1231 if (regstr[0] != '\0') { 1232 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 1233 (void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen); 1234 } 1235 } 1236 1237 if ((flags & FLG_ASI) != 0 && asistr != NULL) 1238 bprintf(dhp, "\t<%s>", asistr); 1239 1240 return (0); 1241 } 1242 1243 static int 1244 fmt_cpop(dis_handle_t *dhp, uint32_t instr, const inst_t *inp) 1245 { 1246 ifmt_t *f = (ifmt_t *)&instr; 1247 int flags = FLG_P1(REG_CP)|FLG_P2(REG_CP)|FLG_NOIMM|FLG_P3(REG_CP); 1248 1249 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 1250 prt_field("op", f->fcp.op, 2); 1251 prt_field("op3", f->fcp.op3, 6); 1252 prt_field("opc", f->fcp.opc, 9); 1253 prt_field("rs1", f->fcp.rs1, 5); 1254 prt_field("rs2", f->fcp.rs2, 5); 1255 prt_field("rd", f->fcp.rd, 5); 1256 } 1257 1258 prt_name(dhp, inp->in_data.in_def.in_name, 1); 1259 prt_imm(dhp, f->fcp.opc, 0); 1260 1261 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 1262 (void) prt_aluargs(dhp, instr, flags); 1263 1264 return (0); 1265 } 1266 1267 static int 1268 dis_fmt_rdwr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1269 { 1270 const char *psr_str = "%psr"; 1271 const char *wim_str = "%wim"; 1272 const char *tbr_str = "%tbr"; 1273 1274 const char *name = inp->in_data.in_def.in_name; 1275 const char *regstr = NULL; 1276 1277 ifmt_t *f = (ifmt_t *)&instr; 1278 1279 int rd = (idx < 0x30); 1280 int v9 = (dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)); 1281 int ridx = f->f3.rs1; 1282 int i, first; 1283 int pr_rs1 = 1; 1284 int pr_rs2 = 1; 1285 1286 int use_mask = 1; 1287 uint32_t mask; 1288 1289 if (rd == 0) 1290 ridx = f->f3.rd; 1291 1292 switch (idx) { 1293 case 0x28: 1294 /* rd */ 1295 1296 /* stbar */ 1297 if ((f->f3.rd == 0) && (f->f3.rs1 == 15) && (f->f3.i == 0)) { 1298 prt_name(dhp, "stbar", 0); 1299 return (0); 1300 } 1301 1302 /* membar */ 1303 if ((v9 != 0) && (f->f3.rd == 0) && (f->f3.rs1 == 15) && 1304 (f->f3.i == 1) && ((f->i & (1L << 12)) == 0)) { 1305 1306 prt_name(dhp, "membar", 1307 ((f->fmb.cmask != 0) || (f->fmb.mmask != 0))); 1308 1309 first = 0; 1310 1311 for (i = 0; i < 4; ++i) { 1312 if ((f->fmb.cmask & (1L << i)) != 0) { 1313 bprintf(dhp, "%s%s", 1314 (first != 0) ? "|" : "", 1315 membar_cmask[i]); 1316 first = 1; 1317 } 1318 } 1319 1320 for (i = 0; i < 5; ++i) { 1321 if ((f->fmb.mmask & (1L << i)) != 0) { 1322 bprintf(dhp, "%s%s", 1323 (first != 0) ? "|" : "", 1324 membar_mmask[i]); 1325 first = 1; 1326 } 1327 } 1328 1329 return (0); 1330 } 1331 1332 if (v9 != 0) { 1333 regstr = v9_asr_names[ridx]; 1334 mask = v9_asr_rdmask; 1335 } else { 1336 regstr = asr_names[ridx]; 1337 mask = asr_rdmask; 1338 } 1339 break; 1340 1341 case 0x29: 1342 if (v9 != 0) { 1343 regstr = v9_hprivreg_names[ridx]; 1344 mask = v9_hpr_rdmask; 1345 } else { 1346 regstr = psr_str; 1347 use_mask = 0; 1348 } 1349 break; 1350 1351 case 0x2a: 1352 if (v9 != 0) { 1353 regstr = v9_privreg_names[ridx]; 1354 mask = v9_pr_rdmask; 1355 } else { 1356 regstr = wim_str; 1357 use_mask = 0; 1358 } 1359 break; 1360 1361 case 0x2b: 1362 if (v9 != 0) { 1363 /* flushw */ 1364 prt_name(dhp, name, 0); 1365 return (0); 1366 } 1367 1368 regstr = tbr_str; 1369 use_mask = 0; 1370 break; 1371 1372 case 0x30: 1373 if (v9 != 0) { 1374 regstr = v9_asr_names[ridx]; 1375 mask = v9_asr_wrmask; 1376 } else { 1377 regstr = asr_names[ridx]; 1378 mask = asr_wrmask; 1379 } 1380 1381 /* 1382 * sir is shoehorned in here, per Ultrasparc 2007 1383 * hyperprivileged edition, section 7.88, all of 1384 * these must be true to distinguish from WRasr 1385 */ 1386 if (v9 != 0 && f->f3.rd == 15 && f->f3.rs1 == 0 && 1387 f->f3.i == 1) { 1388 prt_name(dhp, "sir", 1); 1389 prt_imm(dhp, sign_extend(f->f3a.simm13, 13), 1390 IMM_SIGNED); 1391 return (0); 1392 } 1393 1394 /* synth: mov */ 1395 if ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1396 == 0) 1397 break; 1398 1399 if (v9 == 0) { 1400 if (f->f3.rs1 == 0) { 1401 name = "mov"; 1402 pr_rs1 = 0; 1403 } 1404 1405 if ((f->f3.i == 0 && f->f3.rs2 == 0) || 1406 (f->f3.i == 1 && f->f3a.simm13 == 0)) { 1407 name = "mov"; 1408 pr_rs2 = 0; 1409 } 1410 } 1411 1412 if (pr_rs1 == 0) 1413 pr_rs2 = 1; 1414 1415 break; 1416 1417 case 0x31: 1418 /* 1419 * NOTE: due to the presence of an overlay entry for another 1420 * table, this case only happens when doing v8 instructions 1421 * only 1422 */ 1423 regstr = psr_str; 1424 use_mask = 0; 1425 break; 1426 1427 case 0x32: 1428 if (v9 != 0) { 1429 regstr = v9_privreg_names[ridx]; 1430 mask = v9_pr_wrmask; 1431 } else { 1432 regstr = wim_str; 1433 use_mask = 0; 1434 } 1435 break; 1436 1437 case 0x33: 1438 if (v9 != 0) { 1439 regstr = v9_hprivreg_names[ridx]; 1440 mask = v9_hpr_wrmask; 1441 } else { 1442 regstr = tbr_str; 1443 use_mask = 0; 1444 } 1445 break; 1446 } 1447 1448 if (regstr == NULL) 1449 return (-1); 1450 1451 if (use_mask != 0 && ((1L << ridx) & mask) == 0) 1452 return (-1); 1453 1454 prt_name(dhp, name, 1); 1455 1456 if (rd != 0) { 1457 bprintf(dhp, "%s, %s", regstr, reg_names[f->f3.rd]); 1458 } else { 1459 if (pr_rs1 == 1) 1460 bprintf(dhp, "%s, ", reg_names[f->f3.rs1]); 1461 1462 if (pr_rs2 != 0) { 1463 if (f->f3.i == 1) 1464 prt_imm(dhp, sign_extend(f->f3a.simm13, 13), 1465 IMM_SIGNED); 1466 else 1467 (void) strlcat(dhp->dh_buf, 1468 reg_names[f->f3.rs2], dhp->dh_buflen); 1469 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 1470 } 1471 1472 (void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen); 1473 } 1474 1475 return (0); 1476 } 1477 1478 /* ARGSUSED3 */ 1479 int 1480 fmt_trap(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1481 { 1482 ifmt_t *f = (ifmt_t *)&instr; 1483 1484 int v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0); 1485 int p_rs1, p_t; 1486 1487 if (f->ftcc.undef != 0) 1488 return (-1); 1489 1490 if (icc_names[f->ftcc.cc] == NULL) 1491 return (-1); 1492 1493 if (f->ftcc.i == 1 && f->ftcc.undef2 != 0) 1494 return (-1); 1495 1496 if (f->ftcc2.i == 0 && f->ftcc2.undef2 != 0) 1497 return (-1); 1498 1499 p_rs1 = ((f->ftcc.rs1 != 0) || 1500 ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0)); 1501 1502 if (f->ftcc.i == 0) { 1503 p_t = (f->f3.rs2 != 0 || p_rs1 == 0); 1504 1505 bprintf(dhp, "%-9s %s%s%s%s%s", inp->in_data.in_def.in_name, 1506 (v9 != 0) ? icc_names[f->ftcc2.cc] : "", 1507 (v9 != 0) ? ", " : "", 1508 (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "", 1509 (p_rs1 != 0) ? " + " : "", 1510 (p_t != 0) ? reg_names[f->f3.rs2] : ""); 1511 } else { 1512 bprintf(dhp, "%-9s %s%s%s%s0x%x", inp->in_data.in_def.in_name, 1513 (v9 != 0) ? icc_names[f->ftcc2.cc] : "", 1514 (v9 != 0) ? ", " : "", 1515 (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "", 1516 (p_rs1 != 0) ? " + " : "", 1517 f->ftcc.immtrap); 1518 } 1519 return (0); 1520 } 1521 1522 static int 1523 prt_shift(dis_handle_t *dhp, uint32_t instr, const inst_t *inp) 1524 { 1525 char name[5]; 1526 uint32_t cnt; 1527 1528 ifmt_t *f = (ifmt_t *)&instr; 1529 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0); 1530 1531 name[0] = '\0'; 1532 (void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name)); 1533 1534 if (f->f3b.i == 1) 1535 cnt = f->f3.rs2; 1536 1537 if (f->f3b.x == 1 && ((dhp->dh_flags & DIS_SPARC_V8) == 0)) { 1538 cnt = f->f3b.shcnt; 1539 (void) strlcat(name, "x", sizeof (name)); 1540 } 1541 1542 prt_name(dhp, name, 1); 1543 1544 if (f->f3b.i == 1) 1545 bprintf(dhp, (octal != 0) ? "%s, 0%lo, %s" : "%s, 0x%lx, %s", 1546 reg_names[f->f3.rs1], cnt, reg_names[f->f3.rd]); 1547 else 1548 bprintf(dhp, "%s, %s, %s", reg_names[f->f3.rs1], 1549 reg_names[f->f3.rs2], reg_names[f->f3.rd]); 1550 1551 return (0); 1552 } 1553 1554 /* ARGSUSED3 */ 1555 static int 1556 prt_jmpl(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1557 { 1558 const char *name = inp->in_data.in_def.in_name; 1559 ifmt_t *f = (ifmt_t *)&instr; 1560 1561 if (f->f3.rd == 15 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)) 1562 name = "call"; 1563 1564 if (f->f3.rd == 0) { 1565 if (f->f3.i == 1 && f->f3a.simm13 == 8) { 1566 if (f->f3.rs1 == 15) { 1567 prt_name(dhp, "retl", 0); 1568 return (0); 1569 } 1570 1571 if (f->f3.rs1 == 31) { 1572 prt_name(dhp, "ret", 0); 1573 return (0); 1574 } 1575 } 1576 1577 name = "jmp"; 1578 } 1579 1580 prt_name(dhp, name, 1); 1581 prt_address(dhp, instr, 1); 1582 1583 if (f->f3.rd == 0) 1584 return (0); 1585 1586 if (f->f3.rd == 15 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)) 1587 return (0); 1588 1589 bprintf(dhp, ", %s", reg_names[f->f3.rd]); 1590 1591 return (0); 1592 } 1593 1594 int 1595 fmt_alu(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1596 { 1597 ifmt_t *f = (ifmt_t *)&instr; 1598 1599 const char *name = inp->in_data.in_def.in_name; 1600 int flags = inp->in_data.in_def.in_flags; 1601 int arg = 0; 1602 1603 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 1604 prt_field("op", f->f3.op, 2); 1605 prt_field("op3", f->f3.op3, 6); 1606 prt_field("rs1", f->f3.rs1, 5); 1607 1608 switch (idx) { 1609 /* TODO: more formats */ 1610 1611 default: 1612 if (f->f3.i == 0) 1613 prt_field("rs2", f->f3.rs2, 5); 1614 else 1615 prt_field("simm13", f->f3a.simm13, 13); 1616 1617 prt_field("rd", f->f3.rd, 5); 1618 } 1619 1620 } 1621 1622 switch (idx) { 1623 case 0x00: 1624 /* add */ 1625 1626 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0) 1627 break; 1628 1629 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1630 f->f3a.simm13 == 1) { 1631 name = "inc"; 1632 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1633 break; 1634 } 1635 1636 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1637 f->f3a.simm13 != 1) { 1638 name = "inc"; 1639 flags = FLG_P1(REG_NONE); 1640 break; 1641 } 1642 break; 1643 1644 case 0x02: 1645 /* or */ 1646 1647 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1648 == 0) 1649 break; 1650 1651 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) != 0) { 1652 if (f->f3.rs1 == f->f3.rd) { 1653 name = "bset"; 1654 flags = FLG_P1(REG_NONE); 1655 break; 1656 } 1657 } 1658 1659 if (((f->f3.i == 0 && f->f3.rs2 == 0) || 1660 (f->f3.i == 1 && f->f3a.simm13 == 0)) && 1661 (f->f3.rs1 == 0)) { 1662 name = "clr"; 1663 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1664 break; 1665 } 1666 1667 if (f->f3.rs1 == 0) { 1668 name = "mov"; 1669 flags = FLG_P1(REG_NONE); 1670 break; 1671 } 1672 break; 1673 1674 case 0x04: 1675 /* sub */ 1676 1677 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1678 == 0) 1679 break; 1680 1681 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 == f->f3.rd) { 1682 name = "neg"; 1683 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE); 1684 break; 1685 } 1686 1687 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 != f->f3.rd) { 1688 name = "neg"; 1689 flags = FLG_P1(REG_NONE); 1690 break; 1691 } 1692 1693 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0) 1694 break; 1695 1696 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1697 f->f3a.simm13 == 1) { 1698 name = "dec"; 1699 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1700 break; 1701 } 1702 1703 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1704 f->f3a.simm13 != 1) { 1705 name = "dec"; 1706 flags = FLG_P1(REG_NONE); 1707 break; 1708 } 1709 break; 1710 1711 case 0x07: 1712 /* xnor */ 1713 1714 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1715 == 0) 1716 break; 1717 1718 /* 1719 * xnor -> not when you have: 1720 * xnor %rs1, 0x0 or %g0, %rd 1721 */ 1722 if ((f->f3.i == 0 && f->f3.rs2 != 0) || 1723 (f->f3.i == 1 && f->f3a.simm13 != 0)) 1724 break; 1725 1726 name = "not"; 1727 1728 if (f->f3.rs1 == f->f3.rd) 1729 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM| 1730 FLG_P3(REG_INT); 1731 else 1732 flags = FLG_P1(REG_INT)|FLG_P2(REG_NONE)|FLG_NOIMM| 1733 FLG_P3(REG_INT); 1734 1735 break; 1736 1737 case 0x10: 1738 /* addcc */ 1739 1740 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0) 1741 break; 1742 1743 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1744 f->f3a.simm13 == 1) { 1745 name = "inccc"; 1746 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1747 break; 1748 } 1749 1750 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1751 f->f3a.simm13 != 1) { 1752 name = "inccc"; 1753 flags = FLG_P1(REG_NONE); 1754 break; 1755 } 1756 break; 1757 1758 case 0x11: 1759 /* andcc */ 1760 1761 if (f->f3.rd != 0) 1762 break; 1763 1764 if ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1765 == 0) 1766 break; 1767 1768 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0) && 1769 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0)) 1770 break; 1771 1772 name = "btst"; 1773 flags = FLG_P1(REG_NONE); 1774 f->f3.rd = f->f3.rs1; 1775 break; 1776 1777 case 0x12: 1778 /* orcc */ 1779 1780 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1781 == 0) 1782 break; 1783 1784 if (f->f3.rs1 == 0 && f->f3.rd == 0 && f->f3.i == 0) { 1785 name = "tst"; 1786 flags = FLG_P1(REG_NONE)|FLG_P3(REG_NONE); 1787 break; 1788 } 1789 1790 if (f->f3.rs2 == 0 && f->f3.rd == 0 && f->f3.i == 0) { 1791 name = "tst"; 1792 flags = FLG_P2(REG_NONE)|FLG_P3(REG_NONE); 1793 break; 1794 } 1795 1796 break; 1797 1798 case 0x14: 1799 /* subcc */ 1800 1801 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1802 == 0) 1803 break; 1804 1805 if (f->f3.rd == 0) { 1806 name = "cmp"; 1807 flags = FLG_P3(REG_NONE); 1808 break; 1809 } 1810 1811 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0) 1812 break; 1813 1814 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1815 f->f3a.simm13 == 1) { 1816 name = "deccc"; 1817 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1818 break; 1819 } 1820 1821 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1822 f->f3a.simm13 != 1) { 1823 name = "deccc"; 1824 flags = FLG_P1(REG_NONE); 1825 break; 1826 } 1827 1828 break; 1829 1830 case 0x25: 1831 case 0x26: 1832 case 0x27: 1833 return (prt_shift(dhp, instr, inp)); 1834 1835 case 0x28: 1836 case 0x29: 1837 case 0x2a: 1838 case 0x2b: 1839 case 0x30: 1840 case 0x31: 1841 case 0x32: 1842 case 0x33: 1843 return (dis_fmt_rdwr(dhp, instr, inp, idx)); 1844 1845 case 0x36: 1846 case 0x37: 1847 /* NOTE: overlayed on v9 */ 1848 if ((dhp->dh_flags & DIS_SPARC_V8) != 0) 1849 return (fmt_cpop(dhp, instr, inp)); 1850 break; 1851 1852 case 0x38: 1853 /* jmpl */ 1854 return (prt_jmpl(dhp, instr, inp, idx)); 1855 1856 case 0x39: 1857 /* rett / return */ 1858 prt_name(dhp, name, 1); 1859 prt_address(dhp, instr, 1); 1860 return (0); 1861 1862 case 0x3b: 1863 /* flush */ 1864 prt_name(dhp, name, 1); 1865 prt_address(dhp, instr, 0); 1866 return (0); 1867 1868 case 0x3c: 1869 case 0x3d: 1870 /* save / restore */ 1871 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1872 == 0) 1873 break; 1874 1875 if (f->f3.rs1 != 0 || f->f3.rs2 != 0 || f->f3.rd != 0) 1876 break; 1877 1878 if (f->f3.i != 0 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0)) 1879 break; 1880 1881 prt_name(dhp, name, 0); 1882 return (0); 1883 } 1884 1885 if (FLG_P1_VAL(flags) != REG_NONE || FLG_P2_VAL(flags) != REG_NONE || 1886 FLG_P3_VAL(flags) != REG_NONE) 1887 arg = 1; 1888 1889 prt_name(dhp, name, (arg != 0)); 1890 prt_aluargs(dhp, instr, flags); 1891 1892 return (0); 1893 } 1894 1895 /* ARGSUSED1 */ 1896 int 1897 fmt_regwin(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1898 { 1899 prt_name(dhp, inp->in_data.in_def.in_name, 0); 1900 return (0); 1901 } 1902 1903 /* ARGSUSED1 */ 1904 int 1905 fmt_trap_ret(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1906 { 1907 ifmt_t *f = (ifmt_t *)&instr; 1908 prt_name(dhp, inp->in_data.in_def.in_name, 1); 1909 1910 if (f->f3.rd == 0xf) { 1911 /* jpriv */ 1912 prt_address(dhp, instr, 1); 1913 } 1914 1915 return (0); 1916 } 1917 1918 /* ARGSUSED3 */ 1919 int 1920 fmt_movcc(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1921 { 1922 ifmt_t *f = (ifmt_t *)&instr; 1923 const char **regs = NULL; 1924 1925 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 1926 prt_field("op", f->f3c.op, 2); 1927 prt_field("op3", f->f3c.op3, 6); 1928 prt_field("cond", f->f3c.cond, 4); 1929 prt_field("cc2", f->f3c.cc2, 1); 1930 prt_field("cc", f->f3c.cc, 2); 1931 prt_field("i", f->f3c.i, 1); 1932 1933 if (f->f3c.i == 0) 1934 prt_field("rs2", f->f3.rs2, 5); 1935 else 1936 prt_field("simm11", f->f3c.simm11, 11); 1937 1938 prt_field("rd", f->f3.rd, 5); 1939 } 1940 1941 if (f->f3c.cc2 == 0) { 1942 regs = fcc_names; 1943 } else { 1944 regs = icc_names; 1945 if (regs[f->f3c.cc] == NULL) 1946 return (-1); 1947 } 1948 1949 prt_name(dhp, inp->in_data.in_def.in_name, 1); 1950 1951 bprintf(dhp, "%s, ", regs[f->f3c.cc]); 1952 1953 if (f->f3c.i == 1) 1954 prt_imm(dhp, sign_extend(f->f3c.simm11, 11), IMM_SIGNED); 1955 else 1956 (void) strlcat(dhp->dh_buf, reg_names[f->f3.rs2], 1957 dhp->dh_buflen); 1958 1959 bprintf(dhp, ", %s", reg_names[f->f3.rd]); 1960 1961 return (0); 1962 } 1963 1964 /* ARGSUSED3 */ 1965 int 1966 fmt_movr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1967 { 1968 ifmt_t *f = (ifmt_t *)&instr; 1969 1970 prt_name(dhp, inp->in_data.in_def.in_name, 1); 1971 1972 bprintf(dhp, "%s, ", reg_names[f->f3d.rs1]); 1973 1974 if (f->f3d.i == 1) 1975 prt_imm(dhp, sign_extend(f->f3d.simm10, 10), IMM_SIGNED); 1976 else 1977 (void) strlcat(dhp->dh_buf, reg_names[f->f3.rs2], 1978 dhp->dh_buflen); 1979 1980 bprintf(dhp, ", %s", reg_names[f->f3.rd]); 1981 1982 return (0); 1983 } 1984 1985 /* ARGSUSED3 */ 1986 int 1987 fmt_fpop1(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1988 { 1989 ifmt_t *f = (ifmt_t *)&instr; 1990 int flags = inp->in_data.in_def.in_flags; 1991 1992 flags |= FLG_NOIMM; 1993 1994 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 1995 prt_field("op", f->f3.op, 2); 1996 prt_field("op3", f->f3.op3, 6); 1997 prt_field("opf", f->fcmp.opf, 9); 1998 prt_field("rs1", f->f3.rs1, 5); 1999 prt_field("rs2", f->f3.rs2, 5); 2000 prt_field("rd", f->f3.rd, 5); 2001 } 2002 2003 prt_name(dhp, inp->in_data.in_def.in_name, 1); 2004 prt_aluargs(dhp, instr, flags); 2005 2006 return (0); 2007 } 2008 2009 int 2010 fmt_fpop2(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2011 { 2012 static const char *condstr_icc[16] = { 2013 "n", "e", "le", "l", "leu", "lu", "neg", "vs", 2014 "a", "nz", "g", "ge", "gu", "geu", "pos", "vc" 2015 }; 2016 2017 static const char *condstr_fcc[16] = { 2018 "n", "nz", "lg", "ul", "l", "ug", "g", "u", 2019 "a", "e", "ue", "ge", "uge", "le", "ule", "o" 2020 }; 2021 2022 ifmt_t *f = (ifmt_t *)&instr; 2023 const char *ccstr = ""; 2024 char name[15]; 2025 2026 int flags = inp->in_data.in_def.in_flags; 2027 int is_cmp = (idx == 0x51 || idx == 0x52 || idx == 0x53 || 2028 idx == 0x55 || idx == 0x56 || idx == 0x57); 2029 int is_fmov = (idx & 0x3f); 2030 int is_v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0); 2031 int is_compat = ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0); 2032 2033 int p_cc = 0; 2034 2035 is_fmov = (is_fmov == 0x1 || is_fmov == 0x2 || is_fmov == 0x3); 2036 2037 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 2038 prt_field("op", f->f3.op, 2); 2039 prt_field("op3", f->f3.op3, 6); 2040 prt_field("opf", f->fcmp.opf, 9); 2041 2042 switch (idx & 0x3f) { 2043 case 0x51: 2044 case 0x52: 2045 case 0x53: 2046 case 0x55: 2047 case 0x56: 2048 case 0x57: 2049 prt_field("cc", f->fcmp.cc, 2); 2050 prt_field("rs1", f->f3.rs1, 5); 2051 prt_field("rs2", f->f3.rs2, 5); 2052 break; 2053 2054 case 0x01: 2055 case 0x02: 2056 case 0x03: 2057 prt_field("opf_low", f->fmv.opf, 6); 2058 prt_field("cond", f->fmv.cond, 4); 2059 prt_field("opf_cc", f->fmv.cc, 3); 2060 prt_field("rs2", f->fmv.rs2, 5); 2061 break; 2062 2063 default: 2064 prt_field("rs1", f->f3.rs1, 5); 2065 prt_field("rs2", f->f3.rs2, 5); 2066 prt_field("rd", f->f3.rd, 5); 2067 } 2068 } 2069 2070 name[0] = '\0'; 2071 (void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name)); 2072 2073 if (is_fmov != 0) { 2074 (void) strlcat(name, 2075 (f->fmv.cc < 4) ? condstr_fcc[f->fmv.cond] 2076 : condstr_icc[f->fmv.cond], 2077 sizeof (name)); 2078 } 2079 2080 prt_name(dhp, name, 1); 2081 2082 if (is_cmp != 0) 2083 ccstr = fcc_names[f->fcmp.cc]; 2084 2085 if (is_fmov != 0) 2086 ccstr = (f->fmv.cc < 4) ? fcc_names[f->fmv.cc & 0x3] 2087 : icc_names[f->fmv.cc & 0x3]; 2088 2089 if (ccstr == NULL) 2090 return (-1); 2091 2092 p_cc = (is_compat == 0 || is_v9 != 0 || 2093 (is_cmp != 0 && f->fcmp.cc != 0) || 2094 (is_fmov != 0 && f->fmv.cc != 0)); 2095 2096 if (p_cc != 0) 2097 bprintf(dhp, "%s, ", ccstr); 2098 2099 prt_aluargs(dhp, instr, flags); 2100 2101 return (0); 2102 } 2103 2104 int 2105 fmt_vis(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2106 { 2107 ifmt_t *f = (ifmt_t *)&instr; 2108 int flags = inp->in_data.in_def.in_flags; 2109 2110 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 2111 prt_field("op", f->f3.op, 2); 2112 prt_field("op3", f->f3.op3, 6); 2113 prt_field("opf", f->fcmp.opf, 9); 2114 2115 if (idx == 0x081) { 2116 prt_field("mode", instr & 02L, 2); 2117 } else { 2118 prt_field("rs1", f->f3.rs1, 5); 2119 prt_field("rs2", f->f3.rs2, 5); 2120 prt_field("rd", f->f3.rd, 5); 2121 } 2122 } 2123 2124 prt_name(dhp, inp->in_data.in_def.in_name, 1); 2125 2126 if (idx == 0x081) { 2127 /* siam */ 2128 bprintf(dhp, "%d", instr & 0x7L); 2129 return (0); 2130 } 2131 2132 prt_aluargs(dhp, instr, flags); 2133 2134 return (0); 2135 } 2136 2137 /* ARGSUSED3 */ 2138 int 2139 fmt_fused(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2140 { 2141 ifmt_t *f = (ifmt_t *)&instr; 2142 int flags = inp->in_data.in_def.in_flags; 2143 2144 prt_name(dhp, inp->in_data.in_def.in_name, 1); 2145 bprintf(dhp, "%s, %s, %s, %s", 2146 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs1), 2147 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs2), 2148 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs3), 2149 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rd)); 2150 2151 return (0); 2152 } 2153 /* 2154 * put name into the output buffer 2155 * if add_space !=0, append a space after it 2156 */ 2157 static void 2158 prt_name(dis_handle_t *dhp, const char *name, int add_space) 2159 { 2160 bprintf(dhp, (add_space == 0) ? "%s" : "%-9s ", name); 2161 } 2162 2163 /* 2164 * For debugging, print out a field of the instruction 2165 * field is the name of the field 2166 * val is the value of the field 2167 * len is the length of the field (in bits) 2168 */ 2169 #if defined(DIS_STANDALONE) 2170 /* ARGSUSED */ 2171 static void 2172 prt_field(const char *field, uint32_t val, int len) 2173 { 2174 2175 } 2176 2177 #else 2178 static void 2179 prt_field(const char *field, uint32_t val, int len) 2180 { 2181 (void) fprintf(stderr, "DISASM: %8s = 0x%-8x (", field, val); 2182 prt_binary(val, len); 2183 (void) fprintf(stderr, ")\n"); 2184 } 2185 #endif /* DIS_STANDALONE */ 2186 2187 /* 2188 * sign extend a val (that is 'bits' bits in length) to a 32-bit signed 2189 * integer 2190 */ 2191 static int32_t 2192 sign_extend(int32_t val, int32_t bits) 2193 { 2194 if ((val & (1L << (bits - 1))) == 0) 2195 return (val); 2196 2197 return ((-1L << bits) | val); 2198 } 2199 2200 /* 2201 * print out an immediate (i.e. constant) value 2202 * val is the value 2203 * format indicates if it is: 2204 * 0 Unsigned 2205 * IMM_SIGNED A signed value (prepend +/- to the value) 2206 * IMM_ADDR Part of an address expression (prepend +/- but with a space 2207 * between the sign and the value for things like [%i1 + 0x55] 2208 */ 2209 static void 2210 prt_imm(dis_handle_t *dhp, uint32_t val, int format) 2211 { 2212 const char *fmtstr = NULL; 2213 int32_t sv = (int32_t)val; 2214 int octal = dhp->dh_flags & DIS_OCTAL; 2215 2216 switch (format) { 2217 case IMM_ADDR: 2218 if (sv < 0) { 2219 sv = -sv; 2220 fmtstr = (octal != 0) ? "- 0%lo" : "- 0x%lx"; 2221 } else { 2222 fmtstr = (octal != 0) ? "+ 0%lo" : "+ 0x%lx"; 2223 } 2224 break; 2225 2226 case IMM_SIGNED: 2227 if (sv < 0) { 2228 sv = -sv; 2229 fmtstr = (octal != 0) ? "-0%lo" : "-0x%lx"; 2230 break; 2231 } 2232 /* fall through */ 2233 2234 default: 2235 fmtstr = (octal != 0) ? "0%lo" : "0x%lx"; 2236 } 2237 2238 bprintf(dhp, fmtstr, sv); 2239 } 2240 2241 /* 2242 * return the symbolic name of a register 2243 * regset is one of the REG_* values indicating which type of register it is 2244 * such as integer, floating point, etc. 2245 * idx is the numeric value of the register 2246 * 2247 * If regset is REG_NONE, an empty, but non-NULL string is returned 2248 * NULL may be returned if the index indicates an invalid register value 2249 * such as with the %icc/%xcc sets 2250 */ 2251 static const char * 2252 get_regname(dis_handle_t *dhp, int regset, uint32_t idx) 2253 { 2254 const char *regname = NULL; 2255 2256 switch (regset) { 2257 case REG_INT: 2258 regname = reg_names[idx]; 2259 break; 2260 2261 case REG_FP: 2262 regname = freg_names[idx]; 2263 break; 2264 2265 case REG_FPD: 2266 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) || 2267 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0)) 2268 regname = fdreg_names[idx]; 2269 else 2270 regname = compat_fdreg_names[idx]; 2271 2272 break; 2273 2274 case REG_FPQ: 2275 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) 2276 regname = fqreg_names[idx]; 2277 else 2278 regname = freg_names[idx]; 2279 2280 break; 2281 2282 case REG_CP: 2283 regname = cpreg_names[idx]; 2284 break; 2285 2286 case REG_ICC: 2287 regname = icc_names[idx]; 2288 break; 2289 2290 case REG_FCC: 2291 regname = fcc_names[idx]; 2292 break; 2293 2294 case REG_FSR: 2295 regname = "%fsr"; 2296 break; 2297 2298 case REG_CSR: 2299 regname = "%csr"; 2300 break; 2301 2302 case REG_CQ: 2303 regname = "%cq"; 2304 break; 2305 2306 case REG_NONE: 2307 regname = ""; 2308 break; 2309 } 2310 2311 return (regname); 2312 } 2313 2314 /* 2315 * output the asi value from the instruction 2316 * 2317 * TODO: investigate if this should perhaps have a mask -- are undefined ASI 2318 * values for an instruction still disassembled?? 2319 */ 2320 static void 2321 prt_asi(dis_handle_t *dhp, uint32_t instr) 2322 { 2323 ifmt_t *f = (ifmt_t *)&instr; 2324 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0); 2325 2326 if (f->f3.i != 0) 2327 bprintf(dhp, "%%asi"); 2328 else 2329 bprintf(dhp, (octal != 0) ? "0%03o" : "0x%02x", f->f3.asi); 2330 2331 } 2332 2333 /* 2334 * put an address expression into the output buffer 2335 * 2336 * instr is the instruction to use 2337 * if nobrackets != 0, [] are not added around the instruction 2338 * 2339 * Currently this option is set when printing out the address portion 2340 * of a jmpl instruction, but otherwise 0 for load/stores 2341 * 2342 * If no debug flags are set, the full expression is output, even when 2343 * %g0 or 0x0 appears in the address 2344 * 2345 * If DIS_DEBUG_SYN_ALL or DIS_DEBUG_COMPAT are set, when %g0 or 0x0 2346 * appear in the address, they are not output. If the wierd (and probably 2347 * shouldn't happen) address of [%g0 + %g0] or [%g0 + 0x0] is encountered, 2348 * [%g0] is output 2349 */ 2350 static void 2351 prt_address(dis_handle_t *dhp, uint32_t instr, int nobrackets) 2352 { 2353 ifmt_t *f = (ifmt_t *)&instr; 2354 int32_t simm13; 2355 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0); 2356 int p1 = ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0); 2357 int p2 = ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0); 2358 2359 if (f->f3a.i == 0) { 2360 p1 |= ((f->f3a.rs1 != 0) || f->f3.rs2 == 0); 2361 p2 |= (f->f3.rs2 != 0); 2362 2363 bprintf(dhp, "%s%s%s%s%s", 2364 (nobrackets == 0) ? "[" : "", 2365 (p1 != 0) ? reg_names[f->f3a.rs1] : "", 2366 (p1 != 0 && p2 != 0) ? " + " : "", 2367 (p2 != 0) ? reg_names[f->f3.rs2] : "", 2368 (nobrackets == 0) ? "]" : ""); 2369 } else { 2370 const char *sign; 2371 2372 simm13 = sign_extend(f->f3a.simm13, 13); 2373 sign = (simm13 < 0) ? "-" : "+"; 2374 2375 p1 |= (f->f3a.rs1 != 0); 2376 p2 |= (p1 == 0 || simm13 != 0); 2377 2378 if (p1 == 0 && simm13 == 0) 2379 p2 = 1; 2380 2381 if (p1 == 0 && simm13 >= 0) 2382 sign = ""; 2383 2384 if (p2 != 0) 2385 bprintf(dhp, 2386 (octal != 0) ? "%s%s%s%s%s0%lo%s" : 2387 "%s%s%s%s%s0x%lx%s", 2388 (nobrackets == 0) ? "[" : "", 2389 (p1 != 0) ? reg_names[f->f3a.rs1] : "", 2390 (p1 != 0) ? " " : "", 2391 sign, 2392 (p1 != 0) ? " " : "", 2393 (simm13 < 0) ? -(simm13) : simm13, 2394 (nobrackets == 0) ? "]" : ""); 2395 else 2396 bprintf(dhp, "%s%s%s", 2397 (nobrackets == 0) ? "[" : "", 2398 reg_names[f->f3a.rs1], 2399 (nobrackets == 0) ? "]" : ""); 2400 } 2401 } 2402 2403 /* 2404 * print out the arguments to an alu operation (add, sub, etc.) 2405 * conatined in 'instr' 2406 * 2407 * alu instructions have the following format: 2408 * %rs1, %rs2, %rd (i == 0) 2409 * %rs1, 0xnnn, %rd (i == 1) 2410 * ^ ^ ^ 2411 * | | | 2412 * p1 p2 p3 2413 * 2414 * flags indicates the register set to use for each position (p1, p2, p3) 2415 * as well as if immediate values (i == 1) are allowed 2416 * 2417 * if flags indicates a specific position has REG_NONE set as it's register 2418 * set, it is omitted from the output. This is primarly used for certain 2419 * floating point operations 2420 */ 2421 static void 2422 prt_aluargs(dis_handle_t *dhp, uint32_t instr, uint32_t flags) 2423 { 2424 ifmt_t *f = (ifmt_t *)&instr; 2425 const char *r1, *r2, *r3; 2426 int p1, p2, p3; 2427 unsigned int opf = 0; 2428 2429 r1 = get_regname(dhp, FLG_P1_VAL(flags), f->f3.rs1); 2430 r2 = get_regname(dhp, FLG_P2_VAL(flags), f->f3.rs2); 2431 r3 = get_regname(dhp, FLG_P3_VAL(flags), f->f3.rd); 2432 2433 p1 = (FLG_P1_VAL(flags) != REG_NONE); 2434 p2 = (((flags & FLG_NOIMM) == 0) || (FLG_P2_VAL(flags) != REG_NONE)); 2435 p3 = (FLG_RD_VAL(flags) != REG_NONE); 2436 2437 if (r1 == NULL || r1[0] == '\0') 2438 p1 = 0; 2439 2440 if (f->f3a.i == 0 && (r2 == NULL || r2[0] == '\0')) 2441 p2 = 0; 2442 2443 if (r3 == NULL || r3[0] == '\0') 2444 p3 = 0; 2445 2446 if ((f->fcmp.op == 2) && (f->fcmp.op3 == 0x36) && (f->fcmp.cc != 0)) 2447 opf = f->fcmp.opf; 2448 2449 if ((opf == 0x151) || (opf == 0x152)) { 2450 (void) strlcat(dhp->dh_buf, r3, dhp->dh_buflen); 2451 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 2452 p3 = 0; 2453 } 2454 2455 if (p1 != 0) { 2456 (void) strlcat(dhp->dh_buf, r1, dhp->dh_buflen); 2457 if (p2 != 0 || p3 != 0) 2458 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 2459 } 2460 2461 if (p2 != 0) { 2462 if (f->f3.i == 0 || ((flags & FLG_NOIMM) != 0)) 2463 (void) strlcat(dhp->dh_buf, r2, dhp->dh_buflen); 2464 else 2465 prt_imm(dhp, sign_extend(f->f3a.simm13, 13), 2466 IMM_SIGNED); 2467 2468 if (p3 != 0) 2469 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 2470 } 2471 2472 if (p3 != 0) 2473 (void) strlcat(dhp->dh_buf, r3, dhp->dh_buflen); 2474 } 2475 2476 static const char * 2477 get_asi_name(uint8_t asi) 2478 { 2479 switch (asi) { 2480 case 0x04: 2481 return ("ASI_N"); 2482 2483 case 0x0c: 2484 return ("ASI_NL"); 2485 2486 case 0x10: 2487 return ("ASI_AIUP"); 2488 2489 case 0x11: 2490 return ("ASI_AIUS"); 2491 2492 case 0x14: 2493 return ("ASI_REAL"); 2494 2495 case 0x15: 2496 return ("ASI_REAL_IO"); 2497 2498 case 0x16: 2499 return ("ASI_BLK_AIUP"); 2500 2501 case 0x17: 2502 return ("ASI_BLK_AIUS"); 2503 2504 case 0x18: 2505 return ("ASI_AIUPL"); 2506 2507 case 0x19: 2508 return ("ASI_AIUSL"); 2509 2510 case 0x1c: 2511 return ("ASI_REAL_L"); 2512 2513 case 0x1d: 2514 return ("ASI_REAL_IO_L"); 2515 2516 case 0x1e: 2517 return ("ASI_BLK_AIUPL"); 2518 2519 case 0x1f: 2520 return ("ASI_BLK_AIUS_L"); 2521 2522 case 0x20: 2523 return ("ASI_SCRATCHPAD"); 2524 2525 case 0x21: 2526 return ("ASI_MMU_CONTEXTID"); 2527 2528 case 0x22: 2529 return ("ASI_TWINX_AIUP"); 2530 2531 case 0x23: 2532 return ("ASI_TWINX_AIUS"); 2533 2534 case 0x25: 2535 return ("ASI_QUEUE"); 2536 2537 case 0x26: 2538 return ("ASI_TWINX_R"); 2539 2540 case 0x27: 2541 return ("ASI_TWINX_N"); 2542 2543 case 0x2a: 2544 return ("ASI_LDTX_AIUPL"); 2545 2546 case 0x2b: 2547 return ("ASI_TWINX_AIUS_L"); 2548 2549 case 0x2e: 2550 return ("ASI_TWINX_REAL_L"); 2551 2552 case 0x2f: 2553 return ("ASI_TWINX_NL"); 2554 2555 case 0x30: 2556 return ("ASI_AIPP"); 2557 2558 case 0x31: 2559 return ("ASI_AIPS"); 2560 2561 case 0x36: 2562 return ("ASI_AIPN"); 2563 2564 case 0x38: 2565 return ("ASI_AIPP_L"); 2566 2567 case 0x39: 2568 return ("ASI_AIPS_L"); 2569 2570 case 0x3e: 2571 return ("ASI_AIPN_L"); 2572 2573 case 0x41: 2574 return ("ASI_CMT_SHARED"); 2575 2576 case 0x4f: 2577 return ("ASI_HYP_SCRATCHPAD"); 2578 2579 case 0x50: 2580 return ("ASI_IMMU"); 2581 2582 case 0x52: 2583 return ("ASI_MMU_REAL"); 2584 2585 case 0x54: 2586 return ("ASI_MMU"); 2587 2588 case 0x55: 2589 return ("ASI_ITLB_DATA_ACCESS_REG"); 2590 2591 case 0x56: 2592 return ("ASI_ITLB_TAG_READ_REG"); 2593 2594 case 0x57: 2595 return ("ASI_IMMU_DEMAP"); 2596 2597 case 0x58: 2598 return ("ASI_DMMU / ASI_UMMU"); 2599 2600 case 0x5c: 2601 return ("ASI_DTLB_DATA_IN_REG"); 2602 2603 case 0x5d: 2604 return ("ASI_DTLB_DATA_ACCESS_REG"); 2605 2606 case 0x5e: 2607 return ("ASI_DTLB_TAG_READ_REG"); 2608 2609 case 0x5f: 2610 return ("ASI_DMMU_DEMAP"); 2611 2612 case 0x63: 2613 return ("ASI_CMT_PER_STRAND / ASI_CMT_PER_CORE"); 2614 2615 case 0x80: 2616 return ("ASI_P"); 2617 2618 case 0x81: 2619 return ("ASI_S"); 2620 2621 case 0x82: 2622 return ("ASI_PNF"); 2623 2624 case 0x83: 2625 return ("ASI_SNF"); 2626 2627 case 0x88: 2628 return ("ASI_PL"); 2629 2630 case 0x89: 2631 return ("ASI_SL"); 2632 2633 case 0x8a: 2634 return ("ASI_PNFL"); 2635 2636 case 0x8b: 2637 return ("ASI_SNFL"); 2638 2639 case 0xc0: 2640 return ("ASI_PST8_P"); 2641 2642 case 0xc1: 2643 return ("ASI_PST8_S"); 2644 2645 case 0xc2: 2646 return ("ASI_PST16_P"); 2647 2648 case 0xc3: 2649 return ("ASI_PST16_S"); 2650 2651 case 0xc4: 2652 return ("ASI_PST32_P"); 2653 2654 case 0xc5: 2655 return ("ASI_PST32_S"); 2656 2657 case 0xc8: 2658 return ("ASI_PST8_PL"); 2659 2660 case 0xc9: 2661 return ("ASI_PST8_SL"); 2662 2663 case 0xca: 2664 return ("ASI_PST16_PL"); 2665 2666 case 0xcb: 2667 return ("ASI_PST16_SL"); 2668 2669 case 0xcc: 2670 return ("ASI_PST32_PL"); 2671 2672 case 0xcd: 2673 return ("ASI_PST32_SL"); 2674 2675 case 0xd0: 2676 return ("ASI_FL8_P"); 2677 2678 case 0xd1: 2679 return ("ASI_FL8_S"); 2680 2681 case 0xd2: 2682 return ("ASI_FL16_P"); 2683 2684 case 0xd3: 2685 return ("ASI_FL16_S"); 2686 2687 case 0xd8: 2688 return ("ASI_FL8_PL"); 2689 2690 case 0xd9: 2691 return ("ASI_FL8_SL"); 2692 2693 case 0xda: 2694 return ("ASI_FL16_PL"); 2695 2696 case 0xdb: 2697 return ("ASI_FL16_SL"); 2698 2699 case 0xe0: 2700 return ("ASI_BLK_COMMIT_P"); 2701 2702 case 0xe1: 2703 return ("ASI_BLK_SOMMIT_S"); 2704 2705 case 0xe2: 2706 return ("ASI_TWINX_P"); 2707 2708 case 0xe3: 2709 return ("ASI_TWINX_S"); 2710 2711 case 0xea: 2712 return ("ASI_TWINX_PL"); 2713 2714 case 0xeb: 2715 return ("ASI_TWINX_SL"); 2716 2717 case 0xf0: 2718 return ("ASI_BLK_P"); 2719 2720 case 0xf1: 2721 return ("ASI_BLK_S"); 2722 2723 case 0xf8: 2724 return ("ASI_BLK_PL"); 2725 2726 case 0xf9: 2727 return ("ASI_BLK_SL"); 2728 2729 default: 2730 return (NULL); 2731 } 2732 } 2733 2734 /* 2735 * just a handy function that takes care of managing the buffer length 2736 * w/ printf 2737 */ 2738 2739 /* 2740 * PRINTF LIKE 1 2741 */ 2742 static void 2743 bprintf(dis_handle_t *dhp, const char *fmt, ...) 2744 { 2745 size_t curlen; 2746 va_list ap; 2747 2748 curlen = strlen(dhp->dh_buf); 2749 2750 va_start(ap, fmt); 2751 (void) vsnprintf(dhp->dh_buf + curlen, dhp->dh_buflen - curlen, fmt, 2752 ap); 2753 va_end(ap); 2754 }