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