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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 2008 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:5; 393 uint32_t cmask:4; 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:4; 400 uint32_t undef:5; 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[4] = { 570 "#Lookaside", "#MemIssue", "#Sync", "#Halt" 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 "%cps", 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 601 */ 602 static const uint32_t v9_asr_rdmask = 0x13cb007d; 603 static const uint32_t v9_asr_wrmask = 0x13fb004d; 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", "%hrstba", "%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 = 0x8000006f; 633 static const uint32_t v9_hpr_wrmask = 0x8000006f; 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 int chkpt = 0; 788 789 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 790 prt_field("op", f->f2.op, 2); 791 prt_field("op2", f->f2.op2, 3); 792 793 switch (FLG_DISP_VAL(flags)) { 794 case DISP22: 795 prt_field("cond", f->f2a.cond, 4); 796 prt_field("a", f->f2a.a, 1); 797 prt_field("disp22", f->f2a.disp22, 22); 798 break; 799 800 case DISP19: 801 prt_field("cond", f->f2a.cond, 4); 802 prt_field("a", f->f2a.a, 1); 803 prt_field("p", f->f2b.p, 1); 804 prt_field("cc", f->f2b.cc, 2); 805 prt_field("disp19", f->f2b.disp19, 19); 806 break; 807 808 case DISP16: 809 prt_field("bit 28", ((instr & (1L << 28)) >> 28), 1); 810 prt_field("rcond", f->f2c.cond, 3); 811 prt_field("p", f->f2c.p, 1); 812 prt_field("rs1", f->f2c.rs1, 5); 813 prt_field("d16hi", f->f2c.d16hi, 2); 814 prt_field("d16lo", f->f2c.d16lo, 14); 815 break; 816 } 817 } 818 819 if (f->f2b.op2 == 0x01 && idx == 0x00 && f->f2b.p == 1 && 820 f->f2b.cc == 0x02 && ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) != 0)) { 821 name = "iprefetch"; 822 flags = FLG_RS1(REG_NONE)|FLG_DISP(DISP19); 823 } 824 825 if (f->f2b.op2 == 0x01 && f->f2b.a == 1 && 826 f->f2b.p == 0 && f->f2b.cond == 0x8 && f->f2b.cc == 0x01) { 827 name = "chkpt"; 828 flags = FLG_RS1(REG_NONE)|FLG_DISP(DISP19); 829 chkpt = 1; 830 } 831 832 833 switch (FLG_DISP_VAL(flags)) { 834 case DISP22: 835 disp = sign_extend(f->f2a.disp22, 22); 836 break; 837 838 case DISP19: 839 disp = sign_extend(f->f2b.disp19, 19); 840 break; 841 842 case DISP16: 843 disp = sign_extend((f->f2c.d16hi << 14)|f->f2c.d16lo, 16); 844 break; 845 846 } 847 848 disp *= 4; 849 850 if ((FLG_RS1_VAL(flags) == REG_ICC) || (FLG_RS1_VAL(flags) == REG_FCC)) 851 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2b.cc); 852 else 853 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2c.rs1); 854 855 if (r == NULL) 856 return (-1); 857 858 if (f->f2a.a == 1) 859 annul = ",a"; 860 861 if ((flags & FLG_PRED) != 0) { 862 if (f->f2b.p == 0) { 863 pred = ",pn"; 864 } else { 865 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0) 866 pred = ",pt"; 867 } 868 } 869 870 if (!chkpt) { 871 (void) snprintf(buf, sizeof (buf), "%s%s%s", name, annul, pred); 872 } else { 873 (void) snprintf(buf, sizeof (buf), "%s", name); 874 } 875 prt_name(dhp, buf, 1); 876 877 878 switch (FLG_DISP_VAL(flags)) { 879 case DISP22: 880 bprintf(dhp, 881 (octal != 0) ? "%s0%-11lo <" : "%s0x%-10lx <", 882 (disp < 0) ? "-" : "+", 883 (disp < 0) ? (-disp) : disp); 884 break; 885 886 case DISP19: 887 if (!chkpt) { 888 bprintf(dhp, 889 (octal != 0) ? "%s, %s0%-5lo <" : 890 "%s, %s0x%-04lx <", 891 r, 892 (disp < 0) ? "-" : "+", 893 (disp < 0) ? (-disp) : disp); 894 } else { 895 bprintf(dhp, 896 (octal != 0) ? "%s0%-5lo <" : "%s0x%-04lx <", 897 (disp < 0) ? "-" : "+", 898 (disp < 0) ? (-disp) : disp); 899 } 900 break; 901 902 case DISP16: 903 bprintf(dhp, 904 (octal != 0) ? "%s, %s0%-6lo <" : "%s, %s0x%-5lx <", 905 r, 906 (disp < 0) ? "-" : "+", 907 (disp < 0) ? (-disp) : disp); 908 break; 909 } 910 911 curlen = strlen(dhp->dh_buf); 912 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp, 913 dhp->dh_buf + curlen, dhp->dh_buflen - curlen - 1, NULL, NULL); 914 915 (void) strlcat(dhp->dh_buf, ">", dhp->dh_buflen); 916 917 return (0); 918 } 919 920 921 922 /* 923 * print out the compare and swap instructions (casa/casxa) 924 * format: casa/casxa [%rs1] imm_asi, %rs2, %rd 925 * casa/casxa [%rs1] %asi, %rs2, %rd 926 * 927 * If DIS_DEBUG_SYN_ALL is set, synthetic instructions are emitted 928 * when an immediate ASI value is given as follows: 929 * 930 * casa [%rs1]#ASI_P, %rs2, %rd -> cas [%rs1], %rs2, %rd 931 * casa [%rs1]#ASI_P_L, %rs2, %rd -> casl [%rs1], %rs2, %rd 932 * casxa [%rs1]#ASI_P, %rs2, %rd -> casx [%rs1], %rs2, %rd 933 * casxa [%rs1]#ASI_P_L, %rs2, %rd -> casxl [%rs1], %rs2, %rd 934 */ 935 static int 936 fmt_cas(dis_handle_t *dhp, uint32_t instr, const char *name) 937 { 938 ifmt_t *f = (ifmt_t *)&instr; 939 const char *asistr = NULL; 940 int noasi = 0; 941 942 asistr = get_asi_name(f->f3.asi); 943 944 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) != 0) { 945 if (f->f3.op3 == 0x3c && f->f3.i == 0) { 946 if (f->f3.asi == 0x80) { 947 noasi = 1; 948 name = "cas"; 949 } 950 951 if (f->f3.asi == 0x88) { 952 noasi = 1; 953 name = "casl"; 954 } 955 } 956 957 if (f->f3.op3 == 0x3e && f->f3.i == 0) { 958 if (f->f3.asi == 0x80) { 959 noasi = 1; 960 name = "casx"; 961 } 962 963 if (f->f3.asi == 0x88) { 964 noasi = 1; 965 name = "casxl"; 966 } 967 } 968 } 969 970 prt_name(dhp, name, 1); 971 972 bprintf(dhp, "[%s]", reg_names[f->f3.rs1]); 973 974 if (noasi == 0) { 975 (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen); 976 prt_asi(dhp, instr); 977 } 978 979 bprintf(dhp, ", %s, %s", reg_names[f->f3.rs2], reg_names[f->f3.rd]); 980 981 if (noasi == 0 && asistr != NULL) 982 bprintf(dhp, "\t<%s>", asistr); 983 984 return (0); 985 } 986 987 /* 988 * format a load/store instruction 989 * format: ldXX [%rs1 + %rs2], %rd load, i==0 990 * ldXX [%rs1 +/- nn], %rd load, i==1 991 * ldXX [%rs1 + %rs2] #XX, %rd load w/ imm_asi, i==0 992 * ldXX [%rs1 +/- nn] %asi, %rd load from asi[%asi], i==1 993 * 994 * stXX %rd, [%rs1 + %rs2] store, i==0 995 * stXX %rd, [%rs1 +/- nn] store, i==1 996 * stXX %rd, [%rs1 + %rs1] #XX store to imm_asi, i==0 997 * stXX %rd, [%rs1 +/-nn] %asi store to asi[%asi], i==1 998 * 999 * The register sets used for %rd are set in the instructions flags field 1000 * The asi variants are used if FLG_ASI is set in the instructions flags field 1001 * 1002 * If DIS_DEBUG_SYNTH_ALL or DIS_DEBUG_COMPAT are set, 1003 * When %rs1, %rs2 or nn are 0, they are not printed, i.e. 1004 * [ %rs1 + 0x0 ], %rd -> [%rs1], %rd for example 1005 * 1006 * The following synthetic instructions are also implemented: 1007 * 1008 * stb %g0, [addr] -> clrb [addr] DIS_DEBUG_SYNTH_ALL 1009 * sth %g0, [addr] -> crlh [addr] DIS_DEBUG_SYNTH_ALL 1010 * stw %g0, [addr] -> clr [addr] DIS_DEBUG_SYNTH_ALL|DIS_DEBUG_COMPAT 1011 * stx %g0, [addr] -> clrx [addr] DIS_DEBUG_SYNTH_ALL 1012 * 1013 * If DIS_DEBUG_COMPAT is set, the following substitutions also take place 1014 * lduw -> ld 1015 * ldtw -> ld 1016 * stuw -> st 1017 * sttw -> st 1018 */ 1019 int 1020 fmt_ls(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1021 { 1022 ifmt_t *f = (ifmt_t *)&instr; 1023 const char *regstr = NULL; 1024 const char *asistr = NULL; 1025 1026 const char *iname = inp->in_data.in_def.in_name; 1027 uint32_t flags = inp->in_data.in_def.in_flags; 1028 1029 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 1030 prt_field("op", f->f3.op, 2); 1031 prt_field("op3", f->f3.op3, 6); 1032 prt_field("rs1", f->f3.rs1, 5); 1033 prt_field("i", f->f3.i, 1); 1034 if (f->f3.i != 0) { 1035 prt_field("simm13", f->f3a.simm13, 13); 1036 } else { 1037 if ((flags & FLG_ASI) != 0) 1038 prt_field("imm_asi", f->f3.asi, 8); 1039 prt_field("rs2", f->f3.rs2, 5); 1040 } 1041 prt_field("rd", f->f3.rd, 5); 1042 } 1043 1044 if (idx == 0x2d || idx == 0x3d) { 1045 /* prefetch / prefetcha */ 1046 1047 prt_name(dhp, iname, 1); 1048 1049 prt_address(dhp, instr, 0); 1050 1051 if (idx == 0x3d) { 1052 (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen); 1053 prt_asi(dhp, instr); 1054 } 1055 1056 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 1057 1058 /* fcn field is the same as rd */ 1059 if (prefetch_str[f->f3.rd] != NULL) 1060 (void) strlcat(dhp->dh_buf, prefetch_str[f->f3.rd], 1061 dhp->dh_buflen); 1062 else 1063 prt_imm(dhp, f->f3.rd, 0); 1064 1065 if (idx == 0x3d && f->f3.i == 0) { 1066 asistr = get_asi_name(f->f3.asi); 1067 if (asistr != NULL) 1068 bprintf(dhp, "\t<%s>", asistr); 1069 } 1070 1071 return (0); 1072 } 1073 1074 /* casa / casxa */ 1075 if (idx == 0x3c || idx == 0x3e) 1076 return (fmt_cas(dhp, instr, iname)); 1077 1078 /* synthetic instructions & special cases */ 1079 switch (idx) { 1080 case 0x00: 1081 /* ld */ 1082 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) 1083 iname = "lduw"; 1084 break; 1085 1086 case 0x03: 1087 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) 1088 iname = "ldtw"; 1089 break; 1090 1091 case 0x04: 1092 /* stw */ 1093 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) 1094 iname = "stuw"; 1095 1096 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1097 == 0) 1098 break; 1099 1100 if (f->f3.rd == 0) { 1101 iname = "clr"; 1102 flags = FLG_RD(REG_NONE); 1103 } 1104 break; 1105 1106 case 0x05: 1107 /* stb */ 1108 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1109 == 0) 1110 break; 1111 1112 if (f->f3.rd == 0) { 1113 iname = "clrb"; 1114 flags = FLG_RD(REG_NONE); 1115 } 1116 break; 1117 1118 case 0x06: 1119 /* sth */ 1120 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1121 == 0) 1122 break; 1123 1124 if (f->f3.rd == 0) { 1125 iname = "clrh"; 1126 flags = FLG_RD(REG_NONE); 1127 } 1128 break; 1129 1130 case 0x07: 1131 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) 1132 iname = "sttw"; 1133 break; 1134 1135 case 0x0e: 1136 /* stx */ 1137 1138 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1139 == 0) 1140 break; 1141 1142 if (f->f3.rd == 0) { 1143 iname = "clrx"; 1144 flags = FLG_RD(REG_NONE); 1145 } 1146 break; 1147 1148 case 0x13: 1149 /* ldtwa */ 1150 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) && 1151 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0)) 1152 iname = "ldtwa"; 1153 break; 1154 1155 case 0x17: 1156 /* sttwa */ 1157 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) && 1158 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0)) 1159 iname = "sttwa"; 1160 break; 1161 1162 case 0x21: 1163 case 0x25: 1164 /* 1165 * on sparcv8 it merely says that rd != 1 should generate an 1166 * exception, on v9, it is illegal 1167 */ 1168 if ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0) 1169 break; 1170 1171 iname = (idx == 0x21) ? "ldx" : "stx"; 1172 1173 if (f->f3.rd > 1) 1174 return (-1); 1175 1176 break; 1177 1178 case 0x31: 1179 /* stda */ 1180 switch (f->f3.asi) { 1181 case 0xc0: 1182 case 0xc1: 1183 case 0xc8: 1184 case 0xc9: 1185 case 0xc2: 1186 case 0xc3: 1187 case 0xca: 1188 case 0xcb: 1189 case 0xc4: 1190 case 0xc5: 1191 case 0xcc: 1192 case 0xcd: 1193 /* 1194 * store partial floating point, only valid w/ 1195 * vis 1196 * 1197 * Somewhat confusingly, it uses the same op 1198 * code as 'stda' -- store double to alternate 1199 * space. It is distinguised by specific 1200 * imm_asi values (as seen above), and 1201 * has a slightly different output syntax 1202 */ 1203 1204 if ((dhp->dh_flags & DIS_SPARC_V9_SGI) == 0) 1205 break; 1206 if (f->f3.i != 0) 1207 break; 1208 prt_name(dhp, iname, 1); 1209 bprintf(dhp, "%s, %s, [%s] ", 1210 get_regname(dhp, REG_FPD, f->f3.rd), 1211 get_regname(dhp, REG_FPD, f->f3.rs2), 1212 get_regname(dhp, REG_FPD, f->f3.rs1)); 1213 prt_asi(dhp, instr); 1214 asistr = get_asi_name(f->f3.asi); 1215 if (asistr != NULL) 1216 bprintf(dhp, "\t<%s>", asistr); 1217 1218 return (0); 1219 1220 default: 1221 break; 1222 } 1223 1224 } 1225 1226 regstr = get_regname(dhp, FLG_RD_VAL(flags), f->f3.rd); 1227 1228 if (f->f3.i == 0) 1229 asistr = get_asi_name(f->f3.asi); 1230 1231 prt_name(dhp, iname, 1); 1232 1233 if ((flags & FLG_STORE) != 0) { 1234 if (regstr[0] != '\0') { 1235 (void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen); 1236 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 1237 } 1238 1239 prt_address(dhp, instr, 0); 1240 if ((flags & FLG_ASI) != 0) { 1241 (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen); 1242 prt_asi(dhp, instr); 1243 } 1244 } else { 1245 prt_address(dhp, instr, 0); 1246 if ((flags & FLG_ASI) != 0) { 1247 (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen); 1248 prt_asi(dhp, instr); 1249 } 1250 1251 if (regstr[0] != '\0') { 1252 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 1253 (void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen); 1254 } 1255 } 1256 1257 if ((flags & FLG_ASI) != 0 && asistr != NULL) 1258 bprintf(dhp, "\t<%s>", asistr); 1259 1260 return (0); 1261 } 1262 1263 static int 1264 fmt_cpop(dis_handle_t *dhp, uint32_t instr, const inst_t *inp) 1265 { 1266 ifmt_t *f = (ifmt_t *)&instr; 1267 int flags = FLG_P1(REG_CP)|FLG_P2(REG_CP)|FLG_NOIMM|FLG_P3(REG_CP); 1268 1269 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 1270 prt_field("op", f->fcp.op, 2); 1271 prt_field("op3", f->fcp.op3, 6); 1272 prt_field("opc", f->fcp.opc, 9); 1273 prt_field("rs1", f->fcp.rs1, 5); 1274 prt_field("rs2", f->fcp.rs2, 5); 1275 prt_field("rd", f->fcp.rd, 5); 1276 } 1277 1278 prt_name(dhp, inp->in_data.in_def.in_name, 1); 1279 prt_imm(dhp, f->fcp.opc, 0); 1280 1281 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 1282 (void) prt_aluargs(dhp, instr, flags); 1283 1284 return (0); 1285 } 1286 1287 static int 1288 dis_fmt_rdwr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1289 { 1290 const char *psr_str = "%psr"; 1291 const char *wim_str = "%wim"; 1292 const char *tbr_str = "%tbr"; 1293 1294 const char *name = inp->in_data.in_def.in_name; 1295 const char *regstr = NULL; 1296 1297 ifmt_t *f = (ifmt_t *)&instr; 1298 1299 int rd = (idx < 0x30); 1300 int v9 = (dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)); 1301 int ridx = f->f3.rs1; 1302 int i, first; 1303 int pr_rs1 = 1; 1304 int pr_rs2 = 1; 1305 1306 int use_mask = 1; 1307 uint32_t mask; 1308 1309 if (rd == 0) 1310 ridx = f->f3.rd; 1311 1312 switch (idx) { 1313 case 0x28: 1314 /* rd */ 1315 1316 /* stbar */ 1317 if ((f->f3.rd == 0) && (f->f3.rs1 == 15) && (f->f3.i == 0)) { 1318 prt_name(dhp, "stbar", 0); 1319 return (0); 1320 } 1321 1322 /* membar */ 1323 if ((v9 != 0) && (f->f3.rd == 0) && (f->f3.rs1 == 15) && 1324 (f->f3.i == 1) && ((f->i & (1L << 12)) == 0)) { 1325 1326 prt_name(dhp, "membar", 1327 ((f->fmb.cmask != 0) || (f->fmb.mmask != 0))); 1328 1329 first = 0; 1330 1331 for (i = 0; i < 5; ++i) { 1332 if ((f->fmb.cmask & (1L << i)) != 0) { 1333 bprintf(dhp, "%s%s", 1334 (first != 0) ? "|" : "", 1335 membar_cmask[i]); 1336 first = 1; 1337 } 1338 } 1339 1340 for (i = 0; i < 5; ++i) { 1341 if ((f->fmb.mmask & (1L << i)) != 0) { 1342 bprintf(dhp, "%s%s", 1343 (first != 0) ? "|" : "", 1344 membar_mmask[i]); 1345 first = 1; 1346 } 1347 } 1348 1349 return (0); 1350 } 1351 1352 if (v9 != 0) { 1353 regstr = v9_asr_names[ridx]; 1354 mask = v9_asr_rdmask; 1355 } else { 1356 regstr = asr_names[ridx]; 1357 mask = asr_rdmask; 1358 } 1359 break; 1360 1361 case 0x29: 1362 if (v9 != 0) { 1363 regstr = v9_hprivreg_names[ridx]; 1364 mask = v9_hpr_rdmask; 1365 } else { 1366 regstr = psr_str; 1367 use_mask = 0; 1368 } 1369 break; 1370 1371 case 0x2a: 1372 if (v9 != 0) { 1373 regstr = v9_privreg_names[ridx]; 1374 mask = v9_pr_rdmask; 1375 } else { 1376 regstr = wim_str; 1377 use_mask = 0; 1378 } 1379 break; 1380 1381 case 0x2b: 1382 if (v9 != 0) { 1383 /* flushw */ 1384 prt_name(dhp, name, 0); 1385 return (0); 1386 } 1387 1388 regstr = tbr_str; 1389 use_mask = 0; 1390 break; 1391 1392 case 0x30: 1393 if (v9 != 0) { 1394 regstr = v9_asr_names[ridx]; 1395 mask = v9_asr_wrmask; 1396 } else { 1397 regstr = asr_names[ridx]; 1398 mask = asr_wrmask; 1399 } 1400 1401 /* 1402 * sir is shoehorned in here, per Ultrasparc 2007 1403 * hyperprivileged edition, section 7.88, all of 1404 * these must be true to distinguish from WRasr 1405 */ 1406 if (v9 != 0 && f->f3.rd == 15 && f->f3.rs1 == 0 && 1407 f->f3.i == 1) { 1408 prt_name(dhp, "sir", 1); 1409 prt_imm(dhp, sign_extend(f->f3a.simm13, 13), 1410 IMM_SIGNED); 1411 return (0); 1412 } 1413 1414 /* synth: mov */ 1415 if ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1416 == 0) 1417 break; 1418 1419 if (v9 == 0) { 1420 if (f->f3.rs1 == 0) { 1421 name = "mov"; 1422 pr_rs1 = 0; 1423 } 1424 1425 if ((f->f3.i == 0 && f->f3.rs2 == 0) || 1426 (f->f3.i == 1 && f->f3a.simm13 == 0)) { 1427 name = "mov"; 1428 pr_rs2 = 0; 1429 } 1430 } 1431 1432 if (pr_rs1 == 0) 1433 pr_rs2 = 1; 1434 1435 break; 1436 1437 case 0x31: 1438 /* 1439 * NOTE: due to the presence of an overlay entry for another 1440 * table, this case only happens when doing v8 instructions 1441 * only 1442 */ 1443 regstr = psr_str; 1444 use_mask = 0; 1445 break; 1446 1447 case 0x32: 1448 if (v9 != 0) { 1449 regstr = v9_privreg_names[ridx]; 1450 mask = v9_pr_wrmask; 1451 } else { 1452 regstr = wim_str; 1453 use_mask = 0; 1454 } 1455 break; 1456 1457 case 0x33: 1458 if (v9 != 0) { 1459 regstr = v9_hprivreg_names[ridx]; 1460 mask = v9_hpr_wrmask; 1461 } else { 1462 regstr = tbr_str; 1463 use_mask = 0; 1464 } 1465 break; 1466 } 1467 1468 if (regstr == NULL) 1469 return (-1); 1470 1471 if (use_mask != 0 && ((1L << ridx) & mask) == 0) 1472 return (-1); 1473 1474 prt_name(dhp, name, 1); 1475 1476 if (rd != 0) { 1477 bprintf(dhp, "%s, %s", regstr, reg_names[f->f3.rd]); 1478 } else { 1479 if (pr_rs1 == 1) 1480 bprintf(dhp, "%s, ", reg_names[f->f3.rs1]); 1481 1482 if (pr_rs2 != 0) { 1483 if (f->f3.i == 1) 1484 prt_imm(dhp, sign_extend(f->f3a.simm13, 13), 1485 IMM_SIGNED); 1486 else 1487 (void) strlcat(dhp->dh_buf, 1488 reg_names[f->f3.rs2], dhp->dh_buflen); 1489 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 1490 } 1491 1492 (void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen); 1493 } 1494 1495 return (0); 1496 } 1497 1498 /* ARGSUSED3 */ 1499 int 1500 fmt_trap(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1501 { 1502 ifmt_t *f = (ifmt_t *)&instr; 1503 1504 int v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0); 1505 int p_rs1, p_t; 1506 char failstr[8] = "fail"; 1507 1508 if (f->ftcc.undef != 0) 1509 return (-1); 1510 1511 if (icc_names[f->ftcc.cc] == NULL) 1512 return (-1); 1513 1514 if (f->ftcc.i == 1 && f->ftcc.undef2 != 0) 1515 return (-1); 1516 1517 if (f->ftcc2.i == 0 && f->ftcc2.undef2 != 0) 1518 return (-1); 1519 1520 p_rs1 = ((f->ftcc.rs1 != 0) || 1521 ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0)); 1522 1523 if (f->ftcc.i == 0) { 1524 p_t = (f->f3.rs2 != 0 || p_rs1 == 0); 1525 1526 bprintf(dhp, "%-9s %s%s%s%s%s", inp->in_data.in_def.in_name, 1527 (v9 != 0) ? icc_names[f->ftcc2.cc] : "", 1528 (v9 != 0) ? ", " : "", 1529 (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "", 1530 (p_rs1 != 0) ? " + " : "", 1531 (p_t != 0) ? reg_names[f->f3.rs2] : ""); 1532 } else { 1533 if ((p_rs1 == 0) && (f->ftcc.immtrap == 0xF)) { 1534 (void) strlcat(failstr, 1535 (const char *)&(inp->in_data.in_def.in_name[1]), 1536 sizeof (failstr)); 1537 1538 prt_name(dhp, failstr, 1); 1539 bprintf(dhp, "%s%s%s", 1540 (v9 != 0) ? icc_names[f->ftcc2.cc] : "", 1541 (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "", 1542 (p_rs1 != 0) ? " + " : ""); 1543 } else { 1544 bprintf(dhp, "%-9s %s%s%s%s0x%x", inp->in_data.in_def.in_name, 1545 (v9 != 0) ? icc_names[f->ftcc2.cc] : "", 1546 (v9 != 0) ? ", " : "", 1547 (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "", 1548 (p_rs1 != 0) ? " + " : "", 1549 f->ftcc.immtrap); 1550 } 1551 } 1552 1553 return (0); 1554 } 1555 1556 static int 1557 prt_shift(dis_handle_t *dhp, uint32_t instr, const inst_t *inp) 1558 { 1559 char name[5]; 1560 uint32_t cnt; 1561 1562 ifmt_t *f = (ifmt_t *)&instr; 1563 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0); 1564 1565 name[0] = '\0'; 1566 (void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name)); 1567 1568 if (f->f3b.i == 1) 1569 cnt = f->f3.rs2; 1570 1571 if (f->f3b.x == 1 && ((dhp->dh_flags & DIS_SPARC_V8) == 0)) { 1572 cnt = f->f3b.shcnt; 1573 (void) strlcat(name, "x", sizeof (name)); 1574 } 1575 1576 prt_name(dhp, name, 1); 1577 1578 if (f->f3b.i == 1) 1579 bprintf(dhp, (octal != 0) ? "%s, 0%lo, %s" : "%s, 0x%lx, %s", 1580 reg_names[f->f3.rs1], cnt, reg_names[f->f3.rd]); 1581 else 1582 bprintf(dhp, "%s, %s, %s", reg_names[f->f3.rs1], 1583 reg_names[f->f3.rs2], reg_names[f->f3.rd]); 1584 1585 return (0); 1586 } 1587 1588 /* ARGSUSED3 */ 1589 static int 1590 prt_jmpl(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1591 { 1592 const char *name = inp->in_data.in_def.in_name; 1593 ifmt_t *f = (ifmt_t *)&instr; 1594 1595 if (f->f3.rd == 15 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)) 1596 name = "call"; 1597 1598 if (f->f3.rd == 0) { 1599 if (f->f3.i == 1 && f->f3a.simm13 == 8) { 1600 if (f->f3.rs1 == 15) { 1601 prt_name(dhp, "retl", 0); 1602 return (0); 1603 } 1604 1605 if (f->f3.rs1 == 31) { 1606 prt_name(dhp, "ret", 0); 1607 return (0); 1608 } 1609 } 1610 1611 name = "jmp"; 1612 } 1613 1614 prt_name(dhp, name, 1); 1615 prt_address(dhp, instr, 1); 1616 1617 if (f->f3.rd == 0) 1618 return (0); 1619 1620 if (f->f3.rd == 15 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)) 1621 return (0); 1622 1623 bprintf(dhp, ", %s", reg_names[f->f3.rd]); 1624 1625 return (0); 1626 } 1627 1628 int 1629 fmt_alu(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1630 { 1631 ifmt_t *f = (ifmt_t *)&instr; 1632 1633 const char *name = inp->in_data.in_def.in_name; 1634 int flags = inp->in_data.in_def.in_flags; 1635 int arg = 0; 1636 1637 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 1638 prt_field("op", f->f3.op, 2); 1639 prt_field("op3", f->f3.op3, 6); 1640 prt_field("rs1", f->f3.rs1, 5); 1641 1642 switch (idx) { 1643 /* TODO: more formats */ 1644 1645 default: 1646 if (f->f3.i == 0) 1647 prt_field("rs2", f->f3.rs2, 5); 1648 else 1649 prt_field("simm13", f->f3a.simm13, 13); 1650 1651 prt_field("rd", f->f3.rd, 5); 1652 } 1653 1654 } 1655 1656 switch (idx) { 1657 case 0x00: 1658 /* add */ 1659 1660 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0) 1661 break; 1662 1663 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1664 f->f3a.simm13 == 1) { 1665 name = "inc"; 1666 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1667 break; 1668 } 1669 1670 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1671 f->f3a.simm13 != 1) { 1672 name = "inc"; 1673 flags = FLG_P1(REG_NONE); 1674 break; 1675 } 1676 break; 1677 1678 case 0x02: 1679 /* or */ 1680 1681 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1682 == 0) 1683 break; 1684 1685 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) != 0) { 1686 if (f->f3.rs1 == f->f3.rd) { 1687 name = "bset"; 1688 flags = FLG_P1(REG_NONE); 1689 break; 1690 } 1691 } 1692 1693 if (((f->f3.i == 0 && f->f3.rs2 == 0) || 1694 (f->f3.i == 1 && f->f3a.simm13 == 0)) && 1695 (f->f3.rs1 == 0)) { 1696 name = "clr"; 1697 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1698 break; 1699 } 1700 1701 if (f->f3.rs1 == 0) { 1702 name = "mov"; 1703 flags = FLG_P1(REG_NONE); 1704 break; 1705 } 1706 break; 1707 1708 case 0x04: 1709 /* sub */ 1710 1711 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1712 == 0) 1713 break; 1714 1715 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 == f->f3.rd) { 1716 name = "neg"; 1717 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE); 1718 break; 1719 } 1720 1721 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 != f->f3.rd) { 1722 name = "neg"; 1723 flags = FLG_P1(REG_NONE); 1724 break; 1725 } 1726 1727 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0) 1728 break; 1729 1730 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1731 f->f3a.simm13 == 1) { 1732 name = "dec"; 1733 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1734 break; 1735 } 1736 1737 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1738 f->f3a.simm13 != 1) { 1739 name = "dec"; 1740 flags = FLG_P1(REG_NONE); 1741 break; 1742 } 1743 break; 1744 1745 case 0x07: 1746 /* xnor */ 1747 1748 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1749 == 0) 1750 break; 1751 1752 /* 1753 * xnor -> not when you have: 1754 * xnor %rs1, 0x0 or %g0, %rd 1755 */ 1756 if ((f->f3.i == 0 && f->f3.rs2 != 0) || 1757 (f->f3.i == 1 && f->f3a.simm13 != 0)) 1758 break; 1759 1760 name = "not"; 1761 1762 if (f->f3.rs1 == f->f3.rd) 1763 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM| 1764 FLG_P3(REG_INT); 1765 else 1766 flags = FLG_P1(REG_INT)|FLG_P2(REG_NONE)|FLG_NOIMM| 1767 FLG_P3(REG_INT); 1768 1769 break; 1770 1771 case 0x10: 1772 /* addcc */ 1773 1774 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0) 1775 break; 1776 1777 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1778 f->f3a.simm13 == 1) { 1779 name = "inccc"; 1780 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1781 break; 1782 } 1783 1784 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1785 f->f3a.simm13 != 1) { 1786 name = "inccc"; 1787 flags = FLG_P1(REG_NONE); 1788 break; 1789 } 1790 break; 1791 1792 case 0x11: 1793 /* andcc */ 1794 1795 if (f->f3.rd != 0) 1796 break; 1797 1798 if ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1799 == 0) 1800 break; 1801 1802 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0) && 1803 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0)) 1804 break; 1805 1806 name = "btst"; 1807 flags = FLG_P1(REG_NONE); 1808 f->f3.rd = f->f3.rs1; 1809 break; 1810 1811 case 0x12: 1812 /* orcc */ 1813 1814 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1815 == 0) 1816 break; 1817 1818 if (f->f3.rs1 == 0 && f->f3.rd == 0 && f->f3.i == 0) { 1819 name = "tst"; 1820 flags = FLG_P1(REG_NONE)|FLG_P3(REG_NONE); 1821 break; 1822 } 1823 1824 if (f->f3.rs2 == 0 && f->f3.rd == 0 && f->f3.i == 0) { 1825 name = "tst"; 1826 flags = FLG_P2(REG_NONE)|FLG_P3(REG_NONE); 1827 break; 1828 } 1829 1830 break; 1831 1832 case 0x14: 1833 /* subcc */ 1834 1835 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1836 == 0) 1837 break; 1838 1839 if (f->f3.rd == 0) { 1840 name = "cmp"; 1841 flags = FLG_P3(REG_NONE); 1842 break; 1843 } 1844 1845 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0) 1846 break; 1847 1848 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1849 f->f3a.simm13 == 1) { 1850 name = "deccc"; 1851 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1852 break; 1853 } 1854 1855 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1856 f->f3a.simm13 != 1) { 1857 name = "deccc"; 1858 flags = FLG_P1(REG_NONE); 1859 break; 1860 } 1861 1862 break; 1863 1864 case 0x25: 1865 case 0x26: 1866 case 0x27: 1867 return (prt_shift(dhp, instr, inp)); 1868 1869 case 0x28: 1870 case 0x29: 1871 case 0x2a: 1872 case 0x2b: 1873 case 0x30: 1874 case 0x31: 1875 case 0x32: 1876 case 0x33: 1877 return (dis_fmt_rdwr(dhp, instr, inp, idx)); 1878 1879 case 0x36: 1880 case 0x37: 1881 /* NOTE: overlayed on v9 */ 1882 if ((dhp->dh_flags & DIS_SPARC_V8) != 0) 1883 return (fmt_cpop(dhp, instr, inp)); 1884 break; 1885 1886 case 0x38: 1887 /* jmpl */ 1888 return (prt_jmpl(dhp, instr, inp, idx)); 1889 1890 case 0x39: 1891 /* rett / return */ 1892 prt_name(dhp, name, 1); 1893 prt_address(dhp, instr, 1); 1894 return (0); 1895 1896 case 0x3b: 1897 if (f->f3.rd == 1) { 1898 /* flusha */ 1899 prt_name(dhp, "flusha", 1); 1900 prt_address(dhp, instr, 0); 1901 (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen); 1902 prt_asi(dhp, instr); 1903 } else { 1904 /* flush */ 1905 prt_name(dhp, name, 1); 1906 prt_address(dhp, instr, 0); 1907 } 1908 return (0); 1909 1910 case 0x3c: 1911 case 0x3d: 1912 /* save / restore */ 1913 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1914 == 0) 1915 break; 1916 1917 if (f->f3.rs1 != 0 || f->f3.rs2 != 0 || f->f3.rd != 0) 1918 break; 1919 1920 if (f->f3.i != 0 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0)) 1921 break; 1922 1923 prt_name(dhp, name, 0); 1924 return (0); 1925 } 1926 1927 if (FLG_P1_VAL(flags) != REG_NONE || FLG_P2_VAL(flags) != REG_NONE || 1928 FLG_P3_VAL(flags) != REG_NONE) 1929 arg = 1; 1930 1931 prt_name(dhp, name, (arg != 0)); 1932 prt_aluargs(dhp, instr, flags); 1933 1934 return (0); 1935 } 1936 1937 /* ARGSUSED1 */ 1938 int 1939 fmt_regwin(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1940 { 1941 prt_name(dhp, inp->in_data.in_def.in_name, 0); 1942 return (0); 1943 } 1944 1945 /* ARGSUSED1 */ 1946 int 1947 fmt_trap_ret(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1948 { 1949 ifmt_t *f = (ifmt_t *)&instr; 1950 prt_name(dhp, inp->in_data.in_def.in_name, 1); 1951 1952 if (f->f3.rd == 0xf) { 1953 /* jpriv */ 1954 prt_address(dhp, instr, 1); 1955 } 1956 1957 return (0); 1958 } 1959 1960 /* ARGSUSED3 */ 1961 int 1962 fmt_movcc(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1963 { 1964 ifmt_t *f = (ifmt_t *)&instr; 1965 const char **regs = NULL; 1966 1967 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 1968 prt_field("op", f->f3c.op, 2); 1969 prt_field("op3", f->f3c.op3, 6); 1970 prt_field("cond", f->f3c.cond, 4); 1971 prt_field("cc2", f->f3c.cc2, 1); 1972 prt_field("cc", f->f3c.cc, 2); 1973 prt_field("i", f->f3c.i, 1); 1974 1975 if (f->f3c.i == 0) 1976 prt_field("rs2", f->f3.rs2, 5); 1977 else 1978 prt_field("simm11", f->f3c.simm11, 11); 1979 1980 prt_field("rd", f->f3.rd, 5); 1981 } 1982 1983 if (f->f3c.cc2 == 0) { 1984 regs = fcc_names; 1985 } else { 1986 regs = icc_names; 1987 if (regs[f->f3c.cc] == NULL) 1988 return (-1); 1989 } 1990 1991 prt_name(dhp, inp->in_data.in_def.in_name, 1); 1992 1993 bprintf(dhp, "%s, ", regs[f->f3c.cc]); 1994 1995 if (f->f3c.i == 1) 1996 prt_imm(dhp, sign_extend(f->f3c.simm11, 11), IMM_SIGNED); 1997 else 1998 (void) strlcat(dhp->dh_buf, reg_names[f->f3.rs2], 1999 dhp->dh_buflen); 2000 2001 bprintf(dhp, ", %s", reg_names[f->f3.rd]); 2002 2003 return (0); 2004 } 2005 2006 /* ARGSUSED3 */ 2007 int 2008 fmt_movr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2009 { 2010 ifmt_t *f = (ifmt_t *)&instr; 2011 2012 prt_name(dhp, inp->in_data.in_def.in_name, 1); 2013 2014 bprintf(dhp, "%s, ", reg_names[f->f3d.rs1]); 2015 2016 if (f->f3d.i == 1) 2017 prt_imm(dhp, sign_extend(f->f3d.simm10, 10), IMM_SIGNED); 2018 else 2019 (void) strlcat(dhp->dh_buf, reg_names[f->f3.rs2], 2020 dhp->dh_buflen); 2021 2022 bprintf(dhp, ", %s", reg_names[f->f3.rd]); 2023 2024 return (0); 2025 } 2026 2027 /* ARGSUSED3 */ 2028 int 2029 fmt_fpop1(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2030 { 2031 ifmt_t *f = (ifmt_t *)&instr; 2032 int flags = inp->in_data.in_def.in_flags; 2033 2034 flags |= FLG_NOIMM; 2035 2036 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 2037 prt_field("op", f->f3.op, 2); 2038 prt_field("op3", f->f3.op3, 6); 2039 prt_field("opf", f->fcmp.opf, 9); 2040 prt_field("rs1", f->f3.rs1, 5); 2041 prt_field("rs2", f->f3.rs2, 5); 2042 prt_field("rd", f->f3.rd, 5); 2043 } 2044 2045 prt_name(dhp, inp->in_data.in_def.in_name, 1); 2046 prt_aluargs(dhp, instr, flags); 2047 2048 return (0); 2049 } 2050 2051 int 2052 fmt_fpop2(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2053 { 2054 static const char *condstr_icc[16] = { 2055 "n", "e", "le", "l", "leu", "lu", "neg", "vs", 2056 "a", "nz", "g", "ge", "gu", "geu", "pos", "vc" 2057 }; 2058 2059 static const char *condstr_fcc[16] = { 2060 "n", "nz", "lg", "ul", "l", "ug", "g", "u", 2061 "a", "e", "ue", "ge", "uge", "le", "ule", "o" 2062 }; 2063 2064 ifmt_t *f = (ifmt_t *)&instr; 2065 const char *ccstr = ""; 2066 char name[15]; 2067 2068 int flags = inp->in_data.in_def.in_flags; 2069 int is_cmp = (idx == 0x51 || idx == 0x52 || idx == 0x53 || 2070 idx == 0x55 || idx == 0x56 || idx == 0x57); 2071 int is_fmov = (idx & 0x3f); 2072 int is_v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0); 2073 int is_compat = ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0); 2074 2075 int p_cc = 0; 2076 2077 is_fmov = (is_fmov == 0x1 || is_fmov == 0x2 || is_fmov == 0x3); 2078 2079 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 2080 prt_field("op", f->f3.op, 2); 2081 prt_field("op3", f->f3.op3, 6); 2082 prt_field("opf", f->fcmp.opf, 9); 2083 2084 switch (idx & 0x3f) { 2085 case 0x51: 2086 case 0x52: 2087 case 0x53: 2088 case 0x55: 2089 case 0x56: 2090 case 0x57: 2091 prt_field("cc", f->fcmp.cc, 2); 2092 prt_field("rs1", f->f3.rs1, 5); 2093 prt_field("rs2", f->f3.rs2, 5); 2094 break; 2095 2096 case 0x01: 2097 case 0x02: 2098 case 0x03: 2099 prt_field("opf_low", f->fmv.opf, 6); 2100 prt_field("cond", f->fmv.cond, 4); 2101 prt_field("opf_cc", f->fmv.cc, 3); 2102 prt_field("rs2", f->fmv.rs2, 5); 2103 break; 2104 2105 default: 2106 prt_field("rs1", f->f3.rs1, 5); 2107 prt_field("rs2", f->f3.rs2, 5); 2108 prt_field("rd", f->f3.rd, 5); 2109 } 2110 } 2111 2112 name[0] = '\0'; 2113 (void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name)); 2114 2115 if (is_fmov != 0) { 2116 (void) strlcat(name, 2117 (f->fmv.cc < 4) ? condstr_fcc[f->fmv.cond] 2118 : condstr_icc[f->fmv.cond], 2119 sizeof (name)); 2120 } 2121 2122 prt_name(dhp, name, 1); 2123 2124 if (is_cmp != 0) 2125 ccstr = fcc_names[f->fcmp.cc]; 2126 2127 if (is_fmov != 0) 2128 ccstr = (f->fmv.cc < 4) ? fcc_names[f->fmv.cc & 0x3] 2129 : icc_names[f->fmv.cc & 0x3]; 2130 2131 if (ccstr == NULL) 2132 return (-1); 2133 2134 p_cc = (is_compat == 0 || is_v9 != 0 || 2135 (is_cmp != 0 && f->fcmp.cc != 0) || 2136 (is_fmov != 0 && f->fmv.cc != 0)); 2137 2138 if (p_cc != 0) 2139 bprintf(dhp, "%s, ", ccstr); 2140 2141 prt_aluargs(dhp, instr, flags); 2142 2143 return (0); 2144 } 2145 2146 int 2147 fmt_vis(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2148 { 2149 ifmt_t *f = (ifmt_t *)&instr; 2150 int flags = inp->in_data.in_def.in_flags; 2151 2152 if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) { 2153 prt_field("op", f->f3.op, 2); 2154 prt_field("op3", f->f3.op3, 6); 2155 prt_field("opf", f->fcmp.opf, 9); 2156 2157 if (idx == 0x081) { 2158 prt_field("mode", instr & 02L, 2); 2159 } else { 2160 prt_field("rs1", f->f3.rs1, 5); 2161 prt_field("rs2", f->f3.rs2, 5); 2162 prt_field("rd", f->f3.rd, 5); 2163 } 2164 } 2165 2166 prt_name(dhp, inp->in_data.in_def.in_name, 1); 2167 2168 if (idx == 0x081) { 2169 /* siam */ 2170 bprintf(dhp, "%d", instr & 0x7L); 2171 return (0); 2172 } 2173 2174 prt_aluargs(dhp, instr, flags); 2175 2176 return (0); 2177 } 2178 2179 /* ARGSUSED3 */ 2180 int 2181 fmt_fused(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2182 { 2183 ifmt_t *f = (ifmt_t *)&instr; 2184 int flags = inp->in_data.in_def.in_flags; 2185 2186 prt_name(dhp, inp->in_data.in_def.in_name, 1); 2187 bprintf(dhp, "%s, %s, %s, %s", 2188 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs1), 2189 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs2), 2190 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs3), 2191 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rd)); 2192 2193 return (0); 2194 } 2195 /* 2196 * put name into the output buffer 2197 * if add_space !=0, append a space after it 2198 */ 2199 static void 2200 prt_name(dis_handle_t *dhp, const char *name, int add_space) 2201 { 2202 bprintf(dhp, (add_space == 0) ? "%s" : "%-9s ", name); 2203 } 2204 2205 /* 2206 * For debugging, print out a field of the instruction 2207 * field is the name of the field 2208 * val is the value of the field 2209 * len is the length of the field (in bits) 2210 */ 2211 #if defined(DIS_STANDALONE) 2212 /* ARGSUSED */ 2213 static void 2214 prt_field(const char *field, uint32_t val, int len) 2215 { 2216 2217 } 2218 2219 #else 2220 static void 2221 prt_field(const char *field, uint32_t val, int len) 2222 { 2223 (void) fprintf(stderr, "DISASM: %8s = 0x%-8x (", field, val); 2224 prt_binary(val, len); 2225 (void) fprintf(stderr, ")\n"); 2226 } 2227 #endif /* DIS_STANDALONE */ 2228 2229 /* 2230 * sign extend a val (that is 'bits' bits in length) to a 32-bit signed 2231 * integer 2232 */ 2233 static int32_t 2234 sign_extend(int32_t val, int32_t bits) 2235 { 2236 if ((val & (1L << (bits - 1))) == 0) 2237 return (val); 2238 2239 return ((-1L << bits) | val); 2240 } 2241 2242 /* 2243 * print out an immediate (i.e. constant) value 2244 * val is the value 2245 * format indicates if it is: 2246 * 0 Unsigned 2247 * IMM_SIGNED A signed value (prepend +/- to the value) 2248 * IMM_ADDR Part of an address expression (prepend +/- but with a space 2249 * between the sign and the value for things like [%i1 + 0x55] 2250 */ 2251 static void 2252 prt_imm(dis_handle_t *dhp, uint32_t val, int format) 2253 { 2254 const char *fmtstr = NULL; 2255 int32_t sv = (int32_t)val; 2256 int octal = dhp->dh_flags & DIS_OCTAL; 2257 2258 switch (format) { 2259 case IMM_ADDR: 2260 if (sv < 0) { 2261 sv = -sv; 2262 fmtstr = (octal != 0) ? "- 0%lo" : "- 0x%lx"; 2263 } else { 2264 fmtstr = (octal != 0) ? "+ 0%lo" : "+ 0x%lx"; 2265 } 2266 break; 2267 2268 case IMM_SIGNED: 2269 if (sv < 0) { 2270 sv = -sv; 2271 fmtstr = (octal != 0) ? "-0%lo" : "-0x%lx"; 2272 break; 2273 } 2274 /* fall through */ 2275 2276 default: 2277 fmtstr = (octal != 0) ? "0%lo" : "0x%lx"; 2278 } 2279 2280 bprintf(dhp, fmtstr, sv); 2281 } 2282 2283 /* 2284 * return the symbolic name of a register 2285 * regset is one of the REG_* values indicating which type of register it is 2286 * such as integer, floating point, etc. 2287 * idx is the numeric value of the register 2288 * 2289 * If regset is REG_NONE, an empty, but non-NULL string is returned 2290 * NULL may be returned if the index indicates an invalid register value 2291 * such as with the %icc/%xcc sets 2292 */ 2293 static const char * 2294 get_regname(dis_handle_t *dhp, int regset, uint32_t idx) 2295 { 2296 const char *regname = NULL; 2297 2298 switch (regset) { 2299 case REG_INT: 2300 regname = reg_names[idx]; 2301 break; 2302 2303 case REG_FP: 2304 regname = freg_names[idx]; 2305 break; 2306 2307 case REG_FPD: 2308 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) || 2309 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0)) 2310 regname = fdreg_names[idx]; 2311 else 2312 regname = compat_fdreg_names[idx]; 2313 2314 break; 2315 2316 case REG_FPQ: 2317 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) 2318 regname = fqreg_names[idx]; 2319 else 2320 regname = freg_names[idx]; 2321 2322 break; 2323 2324 case REG_CP: 2325 regname = cpreg_names[idx]; 2326 break; 2327 2328 case REG_ICC: 2329 regname = icc_names[idx]; 2330 break; 2331 2332 case REG_FCC: 2333 regname = fcc_names[idx]; 2334 break; 2335 2336 case REG_FSR: 2337 regname = "%fsr"; 2338 break; 2339 2340 case REG_CSR: 2341 regname = "%csr"; 2342 break; 2343 2344 case REG_CQ: 2345 regname = "%cq"; 2346 break; 2347 2348 case REG_NONE: 2349 regname = ""; 2350 break; 2351 } 2352 2353 return (regname); 2354 } 2355 2356 /* 2357 * output the asi value from the instruction 2358 * 2359 * TODO: investigate if this should perhaps have a mask -- are undefined ASI 2360 * values for an instruction still disassembled?? 2361 */ 2362 static void 2363 prt_asi(dis_handle_t *dhp, uint32_t instr) 2364 { 2365 ifmt_t *f = (ifmt_t *)&instr; 2366 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0); 2367 2368 if (f->f3.i != 0) 2369 bprintf(dhp, "%%asi"); 2370 else 2371 bprintf(dhp, (octal != 0) ? "0%03o" : "0x%02x", f->f3.asi); 2372 2373 } 2374 2375 /* 2376 * put an address expression into the output buffer 2377 * 2378 * instr is the instruction to use 2379 * if nobrackets != 0, [] are not added around the instruction 2380 * 2381 * Currently this option is set when printing out the address portion 2382 * of a jmpl instruction, but otherwise 0 for load/stores 2383 * 2384 * If no debug flags are set, the full expression is output, even when 2385 * %g0 or 0x0 appears in the address 2386 * 2387 * If DIS_DEBUG_SYN_ALL or DIS_DEBUG_COMPAT are set, when %g0 or 0x0 2388 * appear in the address, they are not output. If the wierd (and probably 2389 * shouldn't happen) address of [%g0 + %g0] or [%g0 + 0x0] is encountered, 2390 * [%g0] is output 2391 */ 2392 static void 2393 prt_address(dis_handle_t *dhp, uint32_t instr, int nobrackets) 2394 { 2395 ifmt_t *f = (ifmt_t *)&instr; 2396 int32_t simm13; 2397 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0); 2398 int p1 = ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0); 2399 int p2 = ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0); 2400 2401 if (f->f3a.i == 0) { 2402 p1 |= ((f->f3a.rs1 != 0) || f->f3.rs2 == 0); 2403 p2 |= (f->f3.rs2 != 0); 2404 2405 bprintf(dhp, "%s%s%s%s%s", 2406 (nobrackets == 0) ? "[" : "", 2407 (p1 != 0) ? reg_names[f->f3a.rs1] : "", 2408 (p1 != 0 && p2 != 0) ? " + " : "", 2409 (p2 != 0) ? reg_names[f->f3.rs2] : "", 2410 (nobrackets == 0) ? "]" : ""); 2411 } else { 2412 const char *sign; 2413 2414 simm13 = sign_extend(f->f3a.simm13, 13); 2415 sign = (simm13 < 0) ? "-" : "+"; 2416 2417 p1 |= (f->f3a.rs1 != 0); 2418 p2 |= (p1 == 0 || simm13 != 0); 2419 2420 if (p1 == 0 && simm13 == 0) 2421 p2 = 1; 2422 2423 if (p1 == 0 && simm13 >= 0) 2424 sign = ""; 2425 2426 if (p2 != 0) 2427 bprintf(dhp, 2428 (octal != 0) ? "%s%s%s%s%s0%lo%s" : 2429 "%s%s%s%s%s0x%lx%s", 2430 (nobrackets == 0) ? "[" : "", 2431 (p1 != 0) ? reg_names[f->f3a.rs1] : "", 2432 (p1 != 0) ? " " : "", 2433 sign, 2434 (p1 != 0) ? " " : "", 2435 (simm13 < 0) ? -(simm13) : simm13, 2436 (nobrackets == 0) ? "]" : ""); 2437 else 2438 bprintf(dhp, "%s%s%s", 2439 (nobrackets == 0) ? "[" : "", 2440 reg_names[f->f3a.rs1], 2441 (nobrackets == 0) ? "]" : ""); 2442 } 2443 } 2444 2445 /* 2446 * print out the arguments to an alu operation (add, sub, etc.) 2447 * conatined in 'instr' 2448 * 2449 * alu instructions have the following format: 2450 * %rs1, %rs2, %rd (i == 0) 2451 * %rs1, 0xnnn, %rd (i == 1) 2452 * ^ ^ ^ 2453 * | | | 2454 * p1 p2 p3 2455 * 2456 * flags indicates the register set to use for each position (p1, p2, p3) 2457 * as well as if immediate values (i == 1) are allowed 2458 * 2459 * if flags indicates a specific position has REG_NONE set as it's register 2460 * set, it is omitted from the output. This is primarly used for certain 2461 * floating point operations 2462 */ 2463 static void 2464 prt_aluargs(dis_handle_t *dhp, uint32_t instr, uint32_t flags) 2465 { 2466 ifmt_t *f = (ifmt_t *)&instr; 2467 const char *r1, *r2, *r3; 2468 int p1, p2, p3; 2469 unsigned int opf = 0; 2470 2471 r1 = get_regname(dhp, FLG_P1_VAL(flags), f->f3.rs1); 2472 r2 = get_regname(dhp, FLG_P2_VAL(flags), f->f3.rs2); 2473 r3 = get_regname(dhp, FLG_P3_VAL(flags), f->f3.rd); 2474 2475 p1 = (FLG_P1_VAL(flags) != REG_NONE); 2476 p2 = (((flags & FLG_NOIMM) == 0) || (FLG_P2_VAL(flags) != REG_NONE)); 2477 p3 = (FLG_RD_VAL(flags) != REG_NONE); 2478 2479 if (r1 == NULL || r1[0] == '\0') 2480 p1 = 0; 2481 2482 if (f->f3a.i == 0 && (r2 == NULL || r2[0] == '\0')) 2483 p2 = 0; 2484 2485 if (r3 == NULL || r3[0] == '\0') 2486 p3 = 0; 2487 2488 if ((f->fcmp.op == 2) && (f->fcmp.op3 == 0x36) && (f->fcmp.cc != 0)) 2489 opf = f->fcmp.opf; 2490 2491 if ((opf == 0x151) || (opf == 0x152)) { 2492 (void) strlcat(dhp->dh_buf, r3, dhp->dh_buflen); 2493 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 2494 p3 = 0; 2495 } 2496 2497 if (p1 != 0) { 2498 (void) strlcat(dhp->dh_buf, r1, dhp->dh_buflen); 2499 if (p2 != 0 || p3 != 0) 2500 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 2501 } 2502 2503 if (p2 != 0) { 2504 if (f->f3.i == 0 || ((flags & FLG_NOIMM) != 0)) 2505 (void) strlcat(dhp->dh_buf, r2, dhp->dh_buflen); 2506 else 2507 prt_imm(dhp, sign_extend(f->f3a.simm13, 13), 2508 IMM_SIGNED); 2509 2510 if (p3 != 0) 2511 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen); 2512 } 2513 2514 if (p3 != 0) 2515 (void) strlcat(dhp->dh_buf, r3, dhp->dh_buflen); 2516 } 2517 2518 static const char * 2519 get_asi_name(uint8_t asi) 2520 { 2521 switch (asi) { 2522 case 0x04: 2523 return ("ASI_N"); 2524 2525 case 0x0c: 2526 return ("ASI_NL"); 2527 2528 case 0x10: 2529 return ("ASI_AIUP"); 2530 2531 case 0x11: 2532 return ("ASI_AIUS"); 2533 2534 case 0x14: 2535 return ("ASI_REAL"); 2536 2537 case 0x15: 2538 return ("ASI_REAL_IO"); 2539 2540 case 0x16: 2541 return ("ASI_BLK_AIUP"); 2542 2543 case 0x17: 2544 return ("ASI_BLK_AIUS"); 2545 2546 case 0x18: 2547 return ("ASI_AIUPL"); 2548 2549 case 0x19: 2550 return ("ASI_AIUSL"); 2551 2552 case 0x1c: 2553 return ("ASI_REAL_L"); 2554 2555 case 0x1d: 2556 return ("ASI_REAL_IO_L"); 2557 2558 case 0x1e: 2559 return ("ASI_BLK_AIUPL"); 2560 2561 case 0x1f: 2562 return ("ASI_BLK_AIUS_L"); 2563 2564 case 0x20: 2565 return ("ASI_SCRATCHPAD"); 2566 2567 case 0x21: 2568 return ("ASI_MMU_CONTEXTID"); 2569 2570 case 0x22: 2571 return ("ASI_TWINX_AIUP"); 2572 2573 case 0x23: 2574 return ("ASI_TWINX_AIUS"); 2575 2576 case 0x25: 2577 return ("ASI_QUEUE"); 2578 2579 case 0x26: 2580 return ("ASI_TWINX_R"); 2581 2582 case 0x27: 2583 return ("ASI_TWINX_N"); 2584 2585 case 0x2a: 2586 return ("ASI_LDTX_AIUPL"); 2587 2588 case 0x2b: 2589 return ("ASI_TWINX_AIUS_L"); 2590 2591 case 0x2e: 2592 return ("ASI_TWINX_REAL_L"); 2593 2594 case 0x2f: 2595 return ("ASI_TWINX_NL"); 2596 2597 case 0x30: 2598 return ("ASI_AIPP"); 2599 2600 case 0x31: 2601 return ("ASI_AIPS"); 2602 2603 case 0x36: 2604 return ("ASI_AIPN"); 2605 2606 case 0x38: 2607 return ("ASI_AIPP_L"); 2608 2609 case 0x39: 2610 return ("ASI_AIPS_L"); 2611 2612 case 0x3e: 2613 return ("ASI_AIPN_L"); 2614 2615 case 0x41: 2616 return ("ASI_CMT_SHARED"); 2617 2618 case 0x4f: 2619 return ("ASI_HYP_SCRATCHPAD"); 2620 2621 case 0x50: 2622 return ("ASI_IMMU"); 2623 2624 case 0x52: 2625 return ("ASI_MMU_REAL"); 2626 2627 case 0x54: 2628 return ("ASI_MMU"); 2629 2630 case 0x55: 2631 return ("ASI_ITLB_DATA_ACCESS_REG"); 2632 2633 case 0x56: 2634 return ("ASI_ITLB_TAG_READ_REG"); 2635 2636 case 0x57: 2637 return ("ASI_IMMU_DEMAP"); 2638 2639 case 0x58: 2640 return ("ASI_DMMU / ASI_UMMU"); 2641 2642 case 0x5c: 2643 return ("ASI_DTLB_DATA_IN_REG"); 2644 2645 case 0x5d: 2646 return ("ASI_DTLB_DATA_ACCESS_REG"); 2647 2648 case 0x5e: 2649 return ("ASI_DTLB_TAG_READ_REG"); 2650 2651 case 0x5f: 2652 return ("ASI_DMMU_DEMAP"); 2653 2654 case 0x63: 2655 return ("ASI_CMT_PER_STRAND / ASI_CMT_PER_CORE"); 2656 2657 case 0x80: 2658 return ("ASI_P"); 2659 2660 case 0x81: 2661 return ("ASI_S"); 2662 2663 case 0x82: 2664 return ("ASI_PNF"); 2665 2666 case 0x83: 2667 return ("ASI_SNF"); 2668 2669 case 0x88: 2670 return ("ASI_PL"); 2671 2672 case 0x89: 2673 return ("ASI_SL"); 2674 2675 case 0x8a: 2676 return ("ASI_PNFL"); 2677 2678 case 0x8b: 2679 return ("ASI_SNFL"); 2680 2681 case 0xc0: 2682 return ("ASI_PST8_P"); 2683 2684 case 0xc1: 2685 return ("ASI_PST8_S"); 2686 2687 case 0xc2: 2688 return ("ASI_PST16_P"); 2689 2690 case 0xc3: 2691 return ("ASI_PST16_S"); 2692 2693 case 0xc4: 2694 return ("ASI_PST32_P"); 2695 2696 case 0xc5: 2697 return ("ASI_PST32_S"); 2698 2699 case 0xc8: 2700 return ("ASI_PST8_PL"); 2701 2702 case 0xc9: 2703 return ("ASI_PST8_SL"); 2704 2705 case 0xca: 2706 return ("ASI_PST16_PL"); 2707 2708 case 0xcb: 2709 return ("ASI_PST16_SL"); 2710 2711 case 0xcc: 2712 return ("ASI_PST32_PL"); 2713 2714 case 0xcd: 2715 return ("ASI_PST32_SL"); 2716 2717 case 0xd0: 2718 return ("ASI_FL8_P"); 2719 2720 case 0xd1: 2721 return ("ASI_FL8_S"); 2722 2723 case 0xd2: 2724 return ("ASI_FL16_P"); 2725 2726 case 0xd3: 2727 return ("ASI_FL16_S"); 2728 2729 case 0xd8: 2730 return ("ASI_FL8_PL"); 2731 2732 case 0xd9: 2733 return ("ASI_FL8_SL"); 2734 2735 case 0xda: 2736 return ("ASI_FL16_PL"); 2737 2738 case 0xdb: 2739 return ("ASI_FL16_SL"); 2740 2741 case 0xe0: 2742 return ("ASI_BLK_COMMIT_P"); 2743 2744 case 0xe1: 2745 return ("ASI_BLK_SOMMIT_S"); 2746 2747 case 0xe2: 2748 return ("ASI_TWINX_P"); 2749 2750 case 0xe3: 2751 return ("ASI_TWINX_S"); 2752 2753 case 0xea: 2754 return ("ASI_TWINX_PL"); 2755 2756 case 0xeb: 2757 return ("ASI_TWINX_SL"); 2758 2759 case 0xf0: 2760 return ("ASI_BLK_P"); 2761 2762 case 0xf1: 2763 return ("ASI_BLK_S"); 2764 2765 case 0xf8: 2766 return ("ASI_BLK_PL"); 2767 2768 case 0xf9: 2769 return ("ASI_BLK_SL"); 2770 2771 default: 2772 return (NULL); 2773 } 2774 } 2775 2776 /* 2777 * just a handy function that takes care of managing the buffer length 2778 * w/ printf 2779 */ 2780 2781 /* 2782 * PRINTF LIKE 1 2783 */ 2784 static void 2785 bprintf(dis_handle_t *dhp, const char *fmt, ...) 2786 { 2787 size_t curlen; 2788 va_list ap; 2789 2790 curlen = strlen(dhp->dh_buf); 2791 2792 va_start(ap, fmt); 2793 (void) vsnprintf(dhp->dh_buf + curlen, dhp->dh_buflen - curlen, fmt, 2794 ap); 2795 va_end(ap); 2796 } 2797