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 <stdarg.h> 36 37 #if !defined(DIS_STANDALONE) 38 #include <stdio.h> 39 #endif /* DIS_STANDALONE */ 40 41 #include "libdisasm.h" 42 #include "libdisasm_impl.h" 43 #include "dis_sparc.h" 44 #include "dis_sparc_fmt.h" 45 46 extern char *strncpy(char *, const char *, size_t); 47 extern size_t strlen(const char *); 48 extern int strcmp(const char *, const char *); 49 extern int strncmp(const char *, const char *, size_t); 50 extern size_t strlcat(char *, const char *, size_t); 51 extern size_t strlcpy(char *, const char *, size_t); 52 extern int snprintf(char *, size_t, const char *, ...); 53 extern int vsnprintf(char *, size_t, const char *, va_list); 54 55 /* 56 * This file has the functions that do all the dirty work of outputting the 57 * disassembled instruction 58 * 59 * All the non-static functions follow the format_fcn (in dis_sparc.h): 60 * Input: 61 * disassembler handle/context 62 * instruction to disassemble 63 * instruction definition pointer (inst_t *) 64 * index in the table of the instruction 65 * Return: 66 * 0 Success 67 * !0 Invalid instruction 68 * 69 * Generally, instructions found in the same table use the same output format 70 * or have a few minor differences (which are described in the 'flags' field 71 * of the instruction definition. In some cases, certain instructions differ 72 * radically enough from those in the same table, that their own format 73 * function is used. 74 * 75 * Typically each table has a unique format function defined in this file. In 76 * some cases (such as branches) a common one for all the tables is used. 77 * 78 * When adding support for new instructions, it is largely a judgement call 79 * as to when a new format function is defined. 80 */ 81 82 /* The various instruction formats of a sparc instruction */ 83 84 #if defined(_BIT_FIELDS_HTOL) 85 typedef struct format1 { 86 uint32_t op:2; 87 uint32_t disp30:30; 88 } format1_t; 89 #elif defined(_BIT_FIELDS_LTOH) 90 typedef struct format1 { 91 uint32_t disp30:30; 92 uint32_t op:2; 93 } format1_t; 94 #else 95 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 96 #endif 97 98 #if defined(_BIT_FIELDS_HTOL) 99 typedef struct format2 { 100 uint32_t op:2; 101 uint32_t rd:5; 102 uint32_t op2:3; 103 uint32_t imm22:22; 104 } format2_t; 105 #elif defined(_BIT_FIELDS_LTOH) 106 typedef struct format2 { 107 uint32_t imm22:22; 108 uint32_t op2:3; 109 uint32_t rd:5; 110 uint32_t op:2; 111 } format2_t; 112 #else 113 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 114 #endif 115 116 #if defined(_BIT_FIELDS_HTOL) 117 typedef struct format2a { 118 uint32_t op:2; 119 uint32_t a:1; 120 uint32_t cond:4; 121 uint32_t op2:3; 122 uint32_t disp22:22; 123 } format2a_t; 124 #elif defined(_BIT_FIELDS_LTOH) 125 typedef struct format2a { 126 uint32_t disp22:22; 127 uint32_t op2:3; 128 uint32_t cond:4; 129 uint32_t a:1; 130 uint32_t op:2; 131 } format2a_t; 132 #else 133 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 134 #endif 135 136 #if defined(_BIT_FIELDS_HTOL) 137 typedef struct format2b { 138 uint32_t op:2; 139 uint32_t a:1; 140 uint32_t cond:4; 141 uint32_t op2:3; 142 uint32_t cc:2; 143 uint32_t p:1; 144 uint32_t disp19:19; 145 } format2b_t; 146 #elif defined(_BIT_FIELDS_LTOH) 147 typedef struct format2b { 148 uint32_t disp19:19; 149 uint32_t p:1; 150 uint32_t cc:2; 151 uint32_t op2:3; 152 uint32_t cond:4; 153 uint32_t a:1; 154 uint32_t op:2; 155 } format2b_t; 156 #else 157 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 158 #endif 159 160 #if defined(_BIT_FIELDS_HTOL) 161 typedef struct format2c { 162 uint32_t op:2; 163 uint32_t a:1; 164 uint32_t cond:4; 165 uint32_t op2:3; 166 uint32_t d16hi:2; 167 uint32_t p:1; 168 uint32_t rs1:5; 169 uint32_t d16lo:14; 170 } format2c_t; 171 #elif defined(_BIT_FIELDS_LTOH) 172 typedef struct format2c { 173 uint32_t d16lo:14; 174 uint32_t rs1:5; 175 uint32_t p:1; 176 uint32_t d16hi:2; 177 uint32_t op2:3; 178 uint32_t cond:4; 179 uint32_t a:1; 180 uint32_t op:2; 181 } format2c_t; 182 #else 183 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 184 #endif 185 186 #if defined(_BIT_FIELDS_HTOL) 187 typedef struct format3 { 188 uint32_t op:2; 189 uint32_t rd:5; 190 uint32_t op3:6; 191 uint32_t rs1:5; 192 uint32_t i:1; 193 uint32_t asi:8; 194 uint32_t rs2:5; 195 } format3_t; 196 #elif defined(_BIT_FIELDS_LTOH) 197 typedef struct format3 { 198 uint32_t rs2:5; 199 uint32_t asi:8; 200 uint32_t i:1; 201 uint32_t rs1:5; 202 uint32_t op3:6; 203 uint32_t rd:5; 204 uint32_t op:2; 205 } format3_t; 206 #else 207 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 208 #endif 209 210 #if defined(_BIT_FIELDS_HTOL) 211 typedef struct format3a { 212 uint32_t op:2; 213 uint32_t rd:5; 214 uint32_t op3:6; 215 uint32_t rs1:5; 216 uint32_t i:1; 217 uint32_t simm13:13; 218 } format3a_t; 219 #elif defined(_BIT_FIELDS_LTOH) 220 typedef struct format3a { 221 uint32_t simm13:13; 222 uint32_t i:1; 223 uint32_t rs1:5; 224 uint32_t op3:6; 225 uint32_t rd:5; 226 uint32_t op:2; 227 } format3a_t; 228 #else 229 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 230 #endif 231 232 #if defined(_BIT_FIELDS_HTOL) 233 typedef struct format3b { 234 uint32_t op:2; 235 uint32_t rd:5; 236 uint32_t op3:6; 237 uint32_t rs1:5; 238 uint32_t i:1; 239 uint32_t x:1; 240 uint32_t undef:6; 241 uint32_t shcnt:6; 242 } format3b_t; 243 #elif defined(_BIT_FIELDS_LTOH) 244 typedef struct format3b { 245 uint32_t shcnt:6; 246 uint32_t undef:6; 247 uint32_t x:1; 248 uint32_t i:1; 249 uint32_t rs1:5; 250 uint32_t op3:6; 251 uint32_t rd:5; 252 uint32_t op:2; 253 } format3b_t; 254 #else 255 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 256 #endif 257 258 #if defined(_BIT_FIELDS_HTOL) 259 typedef struct format3c { 260 uint32_t op:2; 261 uint32_t rd:5; 262 uint32_t op3:6; 263 uint32_t cc2:1; 264 uint32_t cond:4; 265 uint32_t i:1; 266 uint32_t cc:2; 267 uint32_t simm11:11; 268 } format3c_t; 269 #elif defined(_BIT_FIELDS_LTOH) 270 typedef struct format3c { 271 uint32_t simm11:11; 272 uint32_t cc:2; 273 uint32_t i:1; 274 uint32_t cond:4; 275 uint32_t cc2:1; 276 uint32_t op3:6; 277 uint32_t rd:5; 278 uint32_t op:2; 279 } format3c_t; 280 #else 281 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 282 #endif 283 284 #if defined(_BIT_FIELDS_HTOL) 285 typedef struct format3d { 286 uint32_t op:2; 287 uint32_t rd:5; 288 uint32_t op3:6; 289 uint32_t rs1:5; 290 uint32_t i:1; 291 uint32_t rcond:3; 292 uint32_t simm10:10; 293 } format3d_t; 294 #elif defined(_BIT_FIELDS_LTOH) 295 typedef struct format3d { 296 uint32_t simm10:10; 297 uint32_t rcond:3; 298 uint32_t i:1; 299 uint32_t rs1:5; 300 uint32_t op3:6; 301 uint32_t rd:5; 302 uint32_t op:2; 303 } format3d_t; 304 #else 305 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 306 #endif 307 308 #if defined(_BIT_FIELDS_HTOL) 309 typedef struct formatcp { 310 uint32_t op:2; 311 uint32_t rd:5; 312 uint32_t op3:6; 313 uint32_t rs1:5; 314 uint32_t opc:9; 315 uint32_t rs2:5; 316 } formatcp_t; 317 #elif defined(_BIT_FIELDS_LTOH) 318 typedef struct formatcp { 319 uint32_t rs2:5; 320 uint32_t opc:9; 321 uint32_t rs1:5; 322 uint32_t op3:6; 323 uint32_t rd:5; 324 uint32_t op:2; 325 } formatcp_t; 326 #else 327 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 328 #endif 329 330 #if defined(_BIT_FIELDS_HTOL) 331 typedef struct formattcc { 332 uint32_t op:2; 333 uint32_t undef:1; 334 uint32_t cond:4; 335 uint32_t op3:6; 336 uint32_t rs1:5; 337 uint32_t i:1; 338 uint32_t cc:2; 339 uint32_t undef2:3; 340 uint32_t immtrap:8; 341 } formattcc_t; 342 #elif defined(_BIT_FIELDS_LTOH) 343 typedef struct formattcc { 344 uint32_t immtrap:8; 345 uint32_t undef2:3; 346 uint32_t cc:2; 347 uint32_t i:1; 348 uint32_t rs1:5; 349 uint32_t op3:6; 350 uint32_t cond:4; 351 uint32_t undef:1; 352 uint32_t op:2; 353 } formattcc_t; 354 #else 355 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 356 #endif 357 358 #if defined(_BIT_FIELDS_HTOL) 359 typedef struct formattcc2 { 360 uint32_t op:2; 361 uint32_t undef:1; 362 uint32_t cond:4; 363 uint32_t op3:6; 364 uint32_t rs1:5; 365 uint32_t i:1; 366 uint32_t cc:2; 367 uint32_t undef2:6; 368 uint32_t rs2:5; 369 } formattcc2_t; 370 #elif defined(_BIT_FIELDS_LTOH) 371 typedef struct formattcc2 { 372 uint32_t rs2:5; 373 uint32_t undef2:6; 374 uint32_t cc:2; 375 uint32_t i:1; 376 uint32_t rs1:5; 377 uint32_t op3:6; 378 uint32_t cond:4; 379 uint32_t undef:1; 380 uint32_t op:2; 381 } formattcc2_t; 382 #else 383 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 384 #endif 385 386 #if defined(_BIT_FIELDS_HTOL) 387 typedef struct formatmbr { 388 uint32_t op:2; 389 uint32_t rd:5; 390 uint32_t op3:6; 391 uint32_t rs1:5; 392 uint32_t i:1; 393 uint32_t undef:6; 394 uint32_t cmask:3; 395 uint32_t mmask:4; 396 } formatmbr_t; 397 #elif defined(_BIT_FIELDS_LTOH) 398 typedef struct formatmbr { 399 uint32_t mmask:4; 400 uint32_t cmask:3; 401 uint32_t undef:6; 402 uint32_t i:1; 403 uint32_t rs1:5; 404 uint32_t op3:6; 405 uint32_t rd:5; 406 uint32_t op:2; 407 } formatmbr_t; 408 #else 409 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 410 #endif 411 412 #if defined(_BIT_FIELDS_HTOL) 413 typedef struct formatfcmp { 414 uint32_t op:2; 415 uint32_t undef:3; 416 uint32_t cc:2; 417 uint32_t op3:6; 418 uint32_t rs1:5; 419 uint32_t opf:9; 420 uint32_t rs2:5; 421 } formatfcmp_t; 422 #elif defined(_BIT_FIELDS_LTOH) 423 typedef struct formatfcmp { 424 uint32_t rs2:5; 425 uint32_t opf:9; 426 uint32_t rs1:5; 427 uint32_t op3:6; 428 uint32_t cc:2; 429 uint32_t undef:3; 430 uint32_t op:2; 431 } formatfcmp_t; 432 #else 433 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 434 #endif 435 436 #if defined(_BIT_FIELDS_HTOL) 437 typedef struct formatfmov { 438 uint32_t op:2; 439 uint32_t rd:5; 440 uint32_t op3:6; 441 uint32_t undef:1; 442 uint32_t cond:4; 443 uint32_t cc:3; 444 uint32_t opf:6; 445 uint32_t rs2:5; 446 } formatfmov_t; 447 #elif defined(_BIT_FIELDS_LTOH) 448 typedef struct formatfmov { 449 uint32_t rs2:5; 450 uint32_t opf:6; 451 uint32_t cc:3; 452 uint32_t cond:4; 453 uint32_t undef:1; 454 uint32_t op3:6; 455 uint32_t rd:5; 456 uint32_t op:2; 457 } formatfmov_t; 458 #else 459 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 460 #endif 461 462 #if defined(_BIT_FIELDS_HTOL) 463 typedef struct formatfused { 464 uint32_t op:2; 465 uint32_t rd:5; 466 uint32_t op3:6; 467 uint32_t rs1:5; 468 uint32_t rs3:5; 469 uint32_t op5:4; 470 uint32_t rs2:5; 471 } formatfused_t; 472 #elif defined(_BIT_FIELDS_LTOH) 473 typedef struct formatfused { 474 uint32_t rs2:5; 475 uint32_t op5:4; 476 uint32_t rs3:5; 477 uint32_t rs1:5; 478 uint32_t op3:6; 479 uint32_t rd:5; 480 uint32_t op:2; 481 } formatfused_t; 482 #else 483 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 484 #endif 485 486 typedef union ifmt { 487 uint32_t i; 488 format1_t f1; 489 format2_t f2; 490 format2a_t f2a; 491 format2b_t f2b; 492 format2c_t f2c; 493 format3_t f3; 494 format3a_t f3a; 495 format3b_t f3b; 496 format3c_t f3c; 497 format3d_t f3d; 498 formatcp_t fcp; 499 formattcc_t ftcc; 500 formattcc2_t ftcc2; 501 formatfcmp_t fcmp; 502 formatmbr_t fmb; 503 formatfmov_t fmv; 504 formatfused_t fused; 505 } ifmt_t; 506 507 /* integer register names */ 508 static const char *reg_names[32] = { 509 "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7", 510 "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7", 511 "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", 512 "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7" 513 }; 514 515 /* floating point register names */ 516 static const char *freg_names[32] = { 517 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", 518 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15", 519 "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23", 520 "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31" 521 }; 522 523 /* double precision register names */ 524 static const char *fdreg_names[32] = { 525 "%d0", "%d32", "%d2", "%d34", "%d4", "%d36", "%d6", "%d38", 526 "%d8", "%d40", "%d10", "%d42", "%d12", "%d44", "%d14", "%d46", 527 "%d16", "%d48", "%d18", "%d50", "%d20", "%d52", "%d22", "%d54", 528 "%d24", "%d56", "%d26", "%d58", "%d28", "%d60", "%d30", "%d62" 529 }; 530 531 static const char *compat_fdreg_names[32] = { 532 "%f0", "%f32", "%f2", "%f34", "%f4", "%f36", "%f6", "%f38", 533 "%f8", "%f40", "%f10", "%f42", "%f12", "%f44", "%f14", "%f46", 534 "%f16", "%f48", "%f18", "%f50", "%f20", "%f52", "%f22", "%f54", 535 "%f24", "%f56", "%f26", "%f58", "%f28", "%f60", "%f30", "%f62" 536 }; 537 538 539 static const char *fqreg_names[32] = { 540 "%q0", "%q32", "%f2", "%f3", "%f4", "%q4", "%q36", "%f6", 541 "%f7", "%q8", "%q40", "%f10", "%f11", "%q12", "%q44", "%f14", 542 "%f15", "%q16", "%q48", "%f18", "%f19", "%q20", "%q52", "%f22", 543 "%f23", "%q24", "%q56", "%f26", "%f27", "%q28", "%q60", "%f30", 544 }; 545 546 547 /* coprocessor register names -- sparcv8 only */ 548 static const char *cpreg_names[32] = { 549 "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7", 550 "%c8", "%c9", "%c10", "%c11", "%c12", "%c13", "%c14", "%c15", 551 "%c16", "%c17", "%c18", "%c19", "%c20", "%c21", "%c22", "%c23", 552 "%c24", "%c25", "%c26", "%c27", "%c28", "%c29", "%c30", "%c31", 553 }; 554 555 /* floating point condition code names */ 556 static const char *fcc_names[4] = { 557 "%fcc0", "%fcc1", "%fcc2", "%fcc3" 558 }; 559 560 /* condition code names */ 561 static const char *icc_names[4] = { 562 "%icc", NULL, "%xcc", NULL 563 }; 564 565 /* bitmask values for membar */ 566 static const char *membar_mmask[4] = { 567 "#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore" 568 }; 569 570 static const char *membar_cmask[3] = { 571 "#Lookaside", "#MemIssue", "#Sync" 572 }; 573 574 /* v8 ancillary state register names */ 575 static const char *asr_names[32] = { 576 "%y", "%asr1", "%asr2", "%asr3", 577 "%asr4", "%asr5", "%asr6", "%asr7", 578 "%asr8", "%asr9", "%asr10", "%asr11", 579 "%asr12", "%asr13", "%asr14", "%asr15", 580 NULL, NULL, NULL, NULL, 581 NULL, NULL, NULL, NULL, 582 NULL, NULL, NULL, NULL, 583 NULL, NULL, NULL, NULL 584 }; 585 static const uint32_t asr_rdmask = 0x0000ffffL; 586 static const uint32_t asr_wrmask = 0x0000ffffL; 587 588 static const char *v9_asr_names[32] = { 589 "%y", NULL, "%ccr", "%asi", 590 "%tick", "%pc", "%fprs", NULL, 591 NULL, NULL, NULL, NULL, 592 NULL, NULL, NULL, NULL, 593 "%pcr", "%pic", "%dcr", "%gsr", 594 "%softint_set", "%softint_clr", "%softint", "%tick_cmpr", 595 "%stick", "%stick_cmpr", NULL, NULL, 596 NULL, NULL, NULL, NULL 597 }; 598 /* 599 * on v9, only certain registers are valid for read or writing 600 * these are bitmasks corresponding to which registers are valid in which 601 * case. Any access to %dcr is illegal. 602 */ 603 static const uint32_t v9_asr_rdmask = 0x03cb007d; 604 static const uint32_t v9_asr_wrmask = 0x03fb004d; 605 606 /* privledged register names on v9 */ 607 /* TODO: compat - NULL to %priv_nn */ 608 static const char *v9_privreg_names[32] = { 609 "%tpc", "%tnpc", "%tstate", "%tt", 610 "%tick", "%tba", "%pstate", "%tl", 611 "%pil", "%cwp", "%cansave", "%canrestore", 612 "%cleanwin", "%otherwin", "%wstate", "%fq", 613 "%gl", NULL, NULL, NULL, 614 NULL, NULL, NULL, NULL, 615 NULL, NULL, NULL, NULL, 616 NULL, NULL, NULL, "%ver" 617 }; 618 619 /* hyper privileged register names on v9 */ 620 static const char *v9_hprivreg_names[32] = { 621 "%hpstate", "%htstate", NULL, "%hintp", 622 NULL, "%htba", "%hver", 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, NULL, 628 NULL, NULL, NULL, "%hstick_cmpr" 629 }; 630 631 static const uint32_t v9_pr_rdmask = 0x80017fff; 632 static const uint32_t v9_pr_wrmask = 0x00017fff; 633 static const uint32_t v9_hpr_rdmask = 0x8000006b; 634 static const uint32_t v9_hpr_wrmask = 0x8000006b; 635 636 static const char *prefetch_str[32] = { 637 "#n_reads", "#one_read", 638 "#n_writes", "#one_write", 639 "#page", NULL, NULL, NULL, 640 NULL, NULL, NULL, NULL, 641 NULL, NULL, NULL, NULL, 642 NULL, "#unified", NULL, NULL, 643 "#n_reads_strong", "#one_read_strong", 644 "#n_writes_strong", "#one_write_strong", 645 NULL, NULL, NULL, NULL, 646 NULL, NULL, NULL, NULL 647 }; 648 649 static void prt_field(const char *, uint32_t, int); 650 651 static const char *get_regname(dis_handle_t *, int, uint32_t); 652 static int32_t sign_extend(int32_t, int32_t); 653 654 static void prt_name(dis_handle_t *, const char *, int); 655 656 #define IMM_SIGNED 0x01 /* Is immediate value signed */ 657 #define IMM_ADDR 0x02 /* Is immediate value part of an address */ 658 static void prt_imm(dis_handle_t *, uint32_t, int); 659 660 static void prt_asi(dis_handle_t *, uint32_t); 661 static const char *get_asi_name(uint8_t); 662 static void prt_address(dis_handle_t *, uint32_t, int); 663 static void prt_aluargs(dis_handle_t *, uint32_t, uint32_t); 664 static void bprintf(dis_handle_t *, const char *, ...); 665 666 /* 667 * print out val (which is 'bitlen' bits long) in binary 668 */ 669 #if defined(DIS_STANDALONE) 670 /* ARGSUSED */ 671 void 672 prt_binary(uint32_t val, int bitlen) 673 { 674 675 } 676 677 #else 678 679 void 680 prt_binary(uint32_t val, int bitlen) 681 { 682 int i; 683 684 for (i = bitlen - 1; i >= 0; --i) { 685 (void) fprintf(stderr, ((val & (1L << i)) != 0) ? "1" : "0"); 686 687 if (i % 4 == 0 && i != 0) 688 (void) fprintf(stderr, " "); 689 } 690 } 691 #endif /* DIS_STANDALONE */ 692 693 694 /* 695 * print out a call instruction 696 * format: call address <name> 697 */ 698 /* ARGSUSED1 */ 699 int 700 fmt_call(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 701 { 702 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 703 ifmt_t *f = (ifmt_t *)&instr; 704 705 int32_t disp; 706 size_t curlen; 707 708 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0); 709 710 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) { 711 prt_field("op", f->f1.op, 2); 712 prt_field("disp30", f->f1.disp30, 30); 713 } 714 715 disp = sign_extend(f->f1.disp30, 30) * 4; 716 717 prt_name(dhp, inp->in_data.in_def.in_name, 1); 718 719 bprintf(dhp, (octal != 0) ? "%s0%-11lo" : "%s0x%-10lx", 720 (disp < 0) ? "-" : "+", 721 (disp < 0) ? (-disp) : disp); 722 723 (void) strlcat(dhx->dhx_buf, " <", dhx->dhx_buflen); 724 725 curlen = strlen(dhx->dhx_buf); 726 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp, 727 dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen - 1, NULL, 728 NULL); 729 (void) strlcat(dhx->dhx_buf, ">", dhx->dhx_buflen); 730 731 732 return (0); 733 } 734 735 int 736 fmt_sethi(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 737 { 738 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 739 ifmt_t *f = (ifmt_t *)&instr; 740 741 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) { 742 prt_field("op", f->f2.op, 2); 743 prt_field("op2", f->f2.op2, 3); 744 prt_field("rd", f->f2.rd, 5); 745 prt_field("imm22", f->f2.imm22, 22); 746 } 747 748 if (idx == 0) { 749 /* unimp / illtrap */ 750 prt_name(dhp, inp->in_data.in_def.in_name, 1); 751 prt_imm(dhp, f->f2.imm22, 0); 752 return (0); 753 } 754 755 if (f->f2.imm22 == 0 && f->f2.rd == 0) { 756 prt_name(dhp, "nop", 0); 757 return (0); 758 } 759 760 /* ?? Should we return -1 if rd == 0 && disp != 0 */ 761 762 prt_name(dhp, inp->in_data.in_def.in_name, 1); 763 764 bprintf(dhp, 765 ((dhp->dh_flags & DIS_OCTAL) != 0) ? 766 "%%hi(0%lo), %s" : "%%hi(0x%lx), %s", 767 f->f2.imm22 << 10, 768 reg_names[f->f2.rd]); 769 770 return (0); 771 } 772 773 /* ARGSUSED3 */ 774 int 775 fmt_branch(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 776 { 777 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 778 const char *name = inp->in_data.in_def.in_name; 779 const char *r = NULL; 780 const char *annul = ""; 781 const char *pred = ""; 782 783 char buf[15]; 784 785 ifmt_t *f = (ifmt_t *)&instr; 786 787 size_t curlen; 788 int32_t disp; 789 uint32_t flags = inp->in_data.in_def.in_flags; 790 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0); 791 792 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) { 793 prt_field("op", f->f2.op, 2); 794 prt_field("op2", f->f2.op2, 3); 795 796 switch (FLG_DISP_VAL(flags)) { 797 case DISP22: 798 prt_field("cond", f->f2a.cond, 4); 799 prt_field("a", f->f2a.a, 1); 800 prt_field("disp22", f->f2a.disp22, 22); 801 break; 802 803 case DISP19: 804 prt_field("cond", f->f2a.cond, 4); 805 prt_field("a", f->f2a.a, 1); 806 prt_field("p", f->f2b.p, 1); 807 prt_field("cc", f->f2b.cc, 2); 808 prt_field("disp19", f->f2b.disp19, 19); 809 break; 810 811 case DISP16: 812 prt_field("bit 28", ((instr & (1L << 28)) >> 28), 1); 813 prt_field("rcond", f->f2c.cond, 3); 814 prt_field("p", f->f2c.p, 1); 815 prt_field("rs1", f->f2c.rs1, 5); 816 prt_field("d16hi", f->f2c.d16hi, 2); 817 prt_field("d16lo", f->f2c.d16lo, 14); 818 break; 819 } 820 } 821 822 if (f->f2b.op2 == 0x01 && idx == 0x00 && f->f2b.p == 1 && 823 f->f2b.cc == 0x02 && ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) != 0)) { 824 name = "iprefetch"; 825 flags = FLG_RS1(REG_NONE)|FLG_DISP(DISP19); 826 } 827 828 829 switch (FLG_DISP_VAL(flags)) { 830 case DISP22: 831 disp = sign_extend(f->f2a.disp22, 22); 832 break; 833 834 case DISP19: 835 disp = sign_extend(f->f2b.disp19, 19); 836 break; 837 838 case DISP16: 839 disp = sign_extend((f->f2c.d16hi << 14)|f->f2c.d16lo, 16); 840 break; 841 842 } 843 844 disp *= 4; 845 846 if ((FLG_RS1_VAL(flags) == REG_ICC) || (FLG_RS1_VAL(flags) == REG_FCC)) 847 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2b.cc); 848 else 849 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2c.rs1); 850 851 if (r == NULL) 852 return (-1); 853 854 if (f->f2a.a == 1) 855 annul = ",a"; 856 857 if ((flags & FLG_PRED) != 0) { 858 if (f->f2b.p == 0) { 859 pred = ",pn"; 860 } else { 861 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0) 862 pred = ",pt"; 863 } 864 } 865 866 (void) snprintf(buf, sizeof (buf), "%s%s%s", name, annul, pred); 867 prt_name(dhp, buf, 1); 868 869 870 switch (FLG_DISP_VAL(flags)) { 871 case DISP22: 872 bprintf(dhp, 873 (octal != 0) ? "%s0%-11lo <" : "%s0x%-10lx <", 874 (disp < 0) ? "-" : "+", 875 (disp < 0) ? (-disp) : disp); 876 break; 877 878 case DISP19: 879 bprintf(dhp, 880 (octal != 0) ? "%s, %s0%-5lo <" : 881 "%s, %s0x%-04lx <", r, 882 (disp < 0) ? "-" : "+", 883 (disp < 0) ? (-disp) : disp); 884 break; 885 886 case DISP16: 887 bprintf(dhp, 888 (octal != 0) ? "%s, %s0%-6lo <" : "%s, %s0x%-5lx <", 889 r, 890 (disp < 0) ? "-" : "+", 891 (disp < 0) ? (-disp) : disp); 892 break; 893 } 894 895 curlen = strlen(dhx->dhx_buf); 896 dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp, 897 dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen - 1, NULL, NULL); 898 899 (void) strlcat(dhx->dhx_buf, ">", dhx->dhx_buflen); 900 901 return (0); 902 } 903 904 905 906 /* 907 * print out the compare and swap instructions (casa/casxa) 908 * format: casa/casxa [%rs1] imm_asi, %rs2, %rd 909 * casa/casxa [%rs1] %asi, %rs2, %rd 910 * 911 * If DIS_DEBUG_SYN_ALL is set, synthetic instructions are emitted 912 * when an immediate ASI value is given as follows: 913 * 914 * casa [%rs1]#ASI_P, %rs2, %rd -> cas [%rs1], %rs2, %rd 915 * casa [%rs1]#ASI_P_L, %rs2, %rd -> casl [%rs1], %rs2, %rd 916 * casxa [%rs1]#ASI_P, %rs2, %rd -> casx [%rs1], %rs2, %rd 917 * casxa [%rs1]#ASI_P_L, %rs2, %rd -> casxl [%rs1], %rs2, %rd 918 */ 919 static int 920 fmt_cas(dis_handle_t *dhp, uint32_t instr, const char *name) 921 { 922 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 923 ifmt_t *f = (ifmt_t *)&instr; 924 const char *asistr = NULL; 925 int noasi = 0; 926 927 asistr = get_asi_name(f->f3.asi); 928 929 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) != 0) { 930 if (f->f3.op3 == 0x3c && f->f3.i == 0) { 931 if (f->f3.asi == 0x80) { 932 noasi = 1; 933 name = "cas"; 934 } 935 936 if (f->f3.asi == 0x88) { 937 noasi = 1; 938 name = "casl"; 939 } 940 } 941 942 if (f->f3.op3 == 0x3e && f->f3.i == 0) { 943 if (f->f3.asi == 0x80) { 944 noasi = 1; 945 name = "casx"; 946 } 947 948 if (f->f3.asi == 0x88) { 949 noasi = 1; 950 name = "casxl"; 951 } 952 } 953 } 954 955 prt_name(dhp, name, 1); 956 957 bprintf(dhp, "[%s]", reg_names[f->f3.rs1]); 958 959 if (noasi == 0) { 960 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen); 961 prt_asi(dhp, instr); 962 } 963 964 bprintf(dhp, ", %s, %s", reg_names[f->f3.rs2], reg_names[f->f3.rd]); 965 966 if (noasi == 0 && asistr != NULL) 967 bprintf(dhp, "\t<%s>", asistr); 968 969 return (0); 970 } 971 972 /* 973 * format a load/store instruction 974 * format: ldXX [%rs1 + %rs2], %rd load, i==0 975 * ldXX [%rs1 +/- nn], %rd load, i==1 976 * ldXX [%rs1 + %rs2] #XX, %rd load w/ imm_asi, i==0 977 * ldXX [%rs1 +/- nn] %asi, %rd load from asi[%asi], i==1 978 * 979 * stXX %rd, [%rs1 + %rs2] store, i==0 980 * stXX %rd, [%rs1 +/- nn] store, i==1 981 * stXX %rd, [%rs1 + %rs1] #XX store to imm_asi, i==0 982 * stXX %rd, [%rs1 +/-nn] %asi store to asi[%asi], i==1 983 * 984 * The register sets used for %rd are set in the instructions flags field 985 * The asi variants are used if FLG_ASI is set in the instructions flags field 986 * 987 * If DIS_DEBUG_SYNTH_ALL or DIS_DEBUG_COMPAT are set, 988 * When %rs1, %rs2 or nn are 0, they are not printed, i.e. 989 * [ %rs1 + 0x0 ], %rd -> [%rs1], %rd for example 990 * 991 * The following synthetic instructions are also implemented: 992 * 993 * stb %g0, [addr] -> clrb [addr] DIS_DEBUG_SYNTH_ALL 994 * sth %g0, [addr] -> crlh [addr] DIS_DEBUG_SYNTH_ALL 995 * stw %g0, [addr] -> clr [addr] DIS_DEBUG_SYNTH_ALL|DIS_DEBUG_COMPAT 996 * stx %g0, [addr] -> clrx [addr] DIS_DEBUG_SYNTH_ALL 997 * 998 * If DIS_DEBUG_COMPAT is set, the following substitutions also take place 999 * lduw -> ld 1000 * ldtw -> ld 1001 * stuw -> st 1002 * sttw -> st 1003 */ 1004 int 1005 fmt_ls(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1006 { 1007 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 1008 ifmt_t *f = (ifmt_t *)&instr; 1009 const char *regstr = NULL; 1010 const char *asistr = NULL; 1011 1012 const char *iname = inp->in_data.in_def.in_name; 1013 uint32_t flags = inp->in_data.in_def.in_flags; 1014 1015 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) { 1016 prt_field("op", f->f3.op, 2); 1017 prt_field("op3", f->f3.op3, 6); 1018 prt_field("rs1", f->f3.rs1, 5); 1019 prt_field("i", f->f3.i, 1); 1020 if (f->f3.i != 0) { 1021 prt_field("simm13", f->f3a.simm13, 13); 1022 } else { 1023 if ((flags & FLG_ASI) != 0) 1024 prt_field("imm_asi", f->f3.asi, 8); 1025 prt_field("rs2", f->f3.rs2, 5); 1026 } 1027 prt_field("rd", f->f3.rd, 5); 1028 } 1029 1030 if (idx == 0x2d || idx == 0x3d) { 1031 /* prefetch / prefetcha */ 1032 1033 prt_name(dhp, iname, 1); 1034 1035 prt_address(dhp, instr, 0); 1036 1037 if (idx == 0x3d) { 1038 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen); 1039 prt_asi(dhp, instr); 1040 } 1041 1042 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen); 1043 1044 /* fcn field is the same as rd */ 1045 if (prefetch_str[f->f3.rd] != NULL) 1046 (void) strlcat(dhx->dhx_buf, prefetch_str[f->f3.rd], 1047 dhx->dhx_buflen); 1048 else 1049 prt_imm(dhp, f->f3.rd, 0); 1050 1051 if (idx == 0x3d && f->f3.i == 0) { 1052 asistr = get_asi_name(f->f3.asi); 1053 if (asistr != NULL) 1054 bprintf(dhp, "\t<%s>", asistr); 1055 } 1056 1057 return (0); 1058 } 1059 1060 /* casa / casxa */ 1061 if (idx == 0x3c || idx == 0x3e) 1062 return (fmt_cas(dhp, instr, iname)); 1063 1064 /* synthetic instructions & special cases */ 1065 switch (idx) { 1066 case 0x00: 1067 /* ld */ 1068 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) 1069 iname = "lduw"; 1070 break; 1071 1072 case 0x03: 1073 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) 1074 iname = "ldtw"; 1075 break; 1076 1077 case 0x04: 1078 /* stw */ 1079 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) 1080 iname = "stuw"; 1081 1082 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1083 == 0) 1084 break; 1085 1086 if (f->f3.rd == 0) { 1087 iname = "clr"; 1088 flags = FLG_RD(REG_NONE); 1089 } 1090 break; 1091 1092 case 0x05: 1093 /* stb */ 1094 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1095 == 0) 1096 break; 1097 1098 if (f->f3.rd == 0) { 1099 iname = "clrb"; 1100 flags = FLG_RD(REG_NONE); 1101 } 1102 break; 1103 1104 case 0x06: 1105 /* sth */ 1106 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1107 == 0) 1108 break; 1109 1110 if (f->f3.rd == 0) { 1111 iname = "clrh"; 1112 flags = FLG_RD(REG_NONE); 1113 } 1114 break; 1115 1116 case 0x07: 1117 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) 1118 iname = "sttw"; 1119 break; 1120 1121 case 0x0e: 1122 /* stx */ 1123 1124 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1125 == 0) 1126 break; 1127 1128 if (f->f3.rd == 0) { 1129 iname = "clrx"; 1130 flags = FLG_RD(REG_NONE); 1131 } 1132 break; 1133 1134 case 0x13: 1135 /* ldtwa */ 1136 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) && 1137 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0)) 1138 iname = "ldtwa"; 1139 break; 1140 1141 case 0x17: 1142 /* sttwa */ 1143 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) && 1144 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0)) 1145 iname = "sttwa"; 1146 break; 1147 1148 case 0x21: 1149 case 0x25: 1150 /* 1151 * on sparcv8 it merely says that rd != 1 should generate an 1152 * exception, on v9, it is illegal 1153 */ 1154 if ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0) 1155 break; 1156 1157 iname = (idx == 0x21) ? "ldx" : "stx"; 1158 1159 if (f->f3.rd > 1) 1160 return (-1); 1161 1162 break; 1163 1164 case 0x31: 1165 /* stda */ 1166 switch (f->f3.asi) { 1167 case 0xc0: 1168 case 0xc1: 1169 case 0xc8: 1170 case 0xc9: 1171 case 0xc2: 1172 case 0xc3: 1173 case 0xca: 1174 case 0xcb: 1175 case 0xc4: 1176 case 0xc5: 1177 case 0xcc: 1178 case 0xcd: 1179 /* 1180 * store partial floating point, only valid w/ 1181 * vis 1182 * 1183 * Somewhat confusingly, it uses the same op 1184 * code as 'stda' -- store double to alternate 1185 * space. It is distinguised by specific 1186 * imm_asi values (as seen above), and 1187 * has a slightly different output syntax 1188 */ 1189 1190 if ((dhp->dh_flags & DIS_SPARC_V9_SGI) == 0) 1191 break; 1192 if (f->f3.i != 0) 1193 break; 1194 prt_name(dhp, iname, 1); 1195 bprintf(dhp, "%s, %s, [%s] ", 1196 get_regname(dhp, REG_FPD, f->f3.rd), 1197 get_regname(dhp, REG_FPD, f->f3.rs2), 1198 get_regname(dhp, REG_FPD, f->f3.rs1)); 1199 prt_asi(dhp, instr); 1200 asistr = get_asi_name(f->f3.asi); 1201 if (asistr != NULL) 1202 bprintf(dhp, "\t<%s>", asistr); 1203 1204 return (0); 1205 1206 default: 1207 break; 1208 } 1209 1210 } 1211 1212 regstr = get_regname(dhp, FLG_RD_VAL(flags), f->f3.rd); 1213 1214 if (f->f3.i == 0) 1215 asistr = get_asi_name(f->f3.asi); 1216 1217 prt_name(dhp, iname, 1); 1218 1219 if ((flags & FLG_STORE) != 0) { 1220 if (regstr[0] != '\0') { 1221 (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen); 1222 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen); 1223 } 1224 1225 prt_address(dhp, instr, 0); 1226 if ((flags & FLG_ASI) != 0) { 1227 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen); 1228 prt_asi(dhp, instr); 1229 } 1230 } else { 1231 prt_address(dhp, instr, 0); 1232 if ((flags & FLG_ASI) != 0) { 1233 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen); 1234 prt_asi(dhp, instr); 1235 } 1236 1237 if (regstr[0] != '\0') { 1238 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen); 1239 (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen); 1240 } 1241 } 1242 1243 if ((flags & FLG_ASI) != 0 && asistr != NULL) 1244 bprintf(dhp, "\t<%s>", asistr); 1245 1246 return (0); 1247 } 1248 1249 static int 1250 fmt_cpop(dis_handle_t *dhp, uint32_t instr, const inst_t *inp) 1251 { 1252 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 1253 ifmt_t *f = (ifmt_t *)&instr; 1254 int flags = FLG_P1(REG_CP)|FLG_P2(REG_CP)|FLG_NOIMM|FLG_P3(REG_CP); 1255 1256 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) { 1257 prt_field("op", f->fcp.op, 2); 1258 prt_field("op3", f->fcp.op3, 6); 1259 prt_field("opc", f->fcp.opc, 9); 1260 prt_field("rs1", f->fcp.rs1, 5); 1261 prt_field("rs2", f->fcp.rs2, 5); 1262 prt_field("rd", f->fcp.rd, 5); 1263 } 1264 1265 prt_name(dhp, inp->in_data.in_def.in_name, 1); 1266 prt_imm(dhp, f->fcp.opc, 0); 1267 1268 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen); 1269 (void) prt_aluargs(dhp, instr, flags); 1270 1271 return (0); 1272 } 1273 1274 static int 1275 dis_fmt_rdwr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1276 { 1277 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 1278 const char *psr_str = "%psr"; 1279 const char *wim_str = "%wim"; 1280 const char *tbr_str = "%tbr"; 1281 1282 const char *name = inp->in_data.in_def.in_name; 1283 const char *regstr = NULL; 1284 1285 ifmt_t *f = (ifmt_t *)&instr; 1286 1287 int rd = (idx < 0x30); 1288 int v9 = (dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)); 1289 int ridx = f->f3.rs1; 1290 int i, first; 1291 int pr_rs1 = 1; 1292 int pr_rs2 = 1; 1293 1294 int use_mask = 1; 1295 uint32_t mask; 1296 1297 if (rd == 0) 1298 ridx = f->f3.rd; 1299 1300 switch (idx) { 1301 case 0x28: 1302 /* rd */ 1303 1304 /* stbar */ 1305 if ((f->f3.rd == 0) && (f->f3.rs1 == 15) && (f->f3.i == 0)) { 1306 prt_name(dhp, "stbar", 0); 1307 return (0); 1308 } 1309 1310 /* membar */ 1311 if ((v9 != 0) && (f->f3.rd == 0) && (f->f3.rs1 == 15) && 1312 (f->f3.i == 1) && ((f->i & (1L << 12)) == 0)) { 1313 1314 prt_name(dhp, "membar", 1315 ((f->fmb.cmask != 0) || (f->fmb.mmask != 0))); 1316 1317 first = 0; 1318 1319 for (i = 0; i < 4; ++i) { 1320 if ((f->fmb.cmask & (1L << i)) != 0) { 1321 bprintf(dhp, "%s%s", 1322 (first != 0) ? "|" : "", 1323 membar_cmask[i]); 1324 first = 1; 1325 } 1326 } 1327 1328 for (i = 0; i < 5; ++i) { 1329 if ((f->fmb.mmask & (1L << i)) != 0) { 1330 bprintf(dhp, "%s%s", 1331 (first != 0) ? "|" : "", 1332 membar_mmask[i]); 1333 first = 1; 1334 } 1335 } 1336 1337 return (0); 1338 } 1339 1340 if (v9 != 0) { 1341 regstr = v9_asr_names[ridx]; 1342 mask = v9_asr_rdmask; 1343 } else { 1344 regstr = asr_names[ridx]; 1345 mask = asr_rdmask; 1346 } 1347 break; 1348 1349 case 0x29: 1350 if (v9 != 0) { 1351 regstr = v9_hprivreg_names[ridx]; 1352 mask = v9_hpr_rdmask; 1353 } else { 1354 regstr = psr_str; 1355 use_mask = 0; 1356 } 1357 break; 1358 1359 case 0x2a: 1360 if (v9 != 0) { 1361 regstr = v9_privreg_names[ridx]; 1362 mask = v9_pr_rdmask; 1363 } else { 1364 regstr = wim_str; 1365 use_mask = 0; 1366 } 1367 break; 1368 1369 case 0x2b: 1370 if (v9 != 0) { 1371 /* flushw */ 1372 prt_name(dhp, name, 0); 1373 return (0); 1374 } 1375 1376 regstr = tbr_str; 1377 use_mask = 0; 1378 break; 1379 1380 case 0x30: 1381 if (v9 != 0) { 1382 regstr = v9_asr_names[ridx]; 1383 mask = v9_asr_wrmask; 1384 } else { 1385 regstr = asr_names[ridx]; 1386 mask = asr_wrmask; 1387 } 1388 1389 /* 1390 * sir is shoehorned in here, per Ultrasparc 2007 1391 * hyperprivileged edition, section 7.88, all of 1392 * these must be true to distinguish from WRasr 1393 */ 1394 if (v9 != 0 && f->f3.rd == 15 && f->f3.rs1 == 0 && 1395 f->f3.i == 1) { 1396 prt_name(dhp, "sir", 1); 1397 prt_imm(dhp, sign_extend(f->f3a.simm13, 13), 1398 IMM_SIGNED); 1399 return (0); 1400 } 1401 1402 /* synth: mov */ 1403 if ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1404 == 0) 1405 break; 1406 1407 if (v9 == 0) { 1408 if (f->f3.rs1 == 0) { 1409 name = "mov"; 1410 pr_rs1 = 0; 1411 } 1412 1413 if ((f->f3.i == 0 && f->f3.rs2 == 0) || 1414 (f->f3.i == 1 && f->f3a.simm13 == 0)) { 1415 name = "mov"; 1416 pr_rs2 = 0; 1417 } 1418 } 1419 1420 if (pr_rs1 == 0) 1421 pr_rs2 = 1; 1422 1423 break; 1424 1425 case 0x31: 1426 /* 1427 * NOTE: due to the presence of an overlay entry for another 1428 * table, this case only happens when doing v8 instructions 1429 * only 1430 */ 1431 regstr = psr_str; 1432 use_mask = 0; 1433 break; 1434 1435 case 0x32: 1436 if (v9 != 0) { 1437 regstr = v9_privreg_names[ridx]; 1438 mask = v9_pr_wrmask; 1439 } else { 1440 regstr = wim_str; 1441 use_mask = 0; 1442 } 1443 break; 1444 1445 case 0x33: 1446 if (v9 != 0) { 1447 regstr = v9_hprivreg_names[ridx]; 1448 mask = v9_hpr_wrmask; 1449 } else { 1450 regstr = tbr_str; 1451 use_mask = 0; 1452 } 1453 break; 1454 } 1455 1456 if (regstr == NULL) 1457 return (-1); 1458 1459 if (use_mask != 0 && ((1L << ridx) & mask) == 0) 1460 return (-1); 1461 1462 prt_name(dhp, name, 1); 1463 1464 if (rd != 0) { 1465 bprintf(dhp, "%s, %s", regstr, reg_names[f->f3.rd]); 1466 } else { 1467 if (pr_rs1 == 1) 1468 bprintf(dhp, "%s, ", reg_names[f->f3.rs1]); 1469 1470 if (pr_rs2 != 0) { 1471 if (f->f3.i == 1) 1472 prt_imm(dhp, sign_extend(f->f3a.simm13, 13), 1473 IMM_SIGNED); 1474 else 1475 (void) strlcat(dhx->dhx_buf, 1476 reg_names[f->f3.rs2], dhx->dhx_buflen); 1477 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen); 1478 } 1479 1480 (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen); 1481 } 1482 1483 return (0); 1484 } 1485 1486 /* ARGSUSED3 */ 1487 int 1488 fmt_trap(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1489 { 1490 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 1491 ifmt_t *f = (ifmt_t *)&instr; 1492 1493 int v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0); 1494 int p_rs1, p_t; 1495 1496 if (f->ftcc.undef != 0) 1497 return (-1); 1498 1499 if (icc_names[f->ftcc.cc] == NULL) 1500 return (-1); 1501 1502 if (f->ftcc.i == 1 && f->ftcc.undef2 != 0) 1503 return (-1); 1504 1505 if (f->ftcc2.i == 0 && f->ftcc2.undef2 != 0) 1506 return (-1); 1507 1508 p_rs1 = ((f->ftcc.rs1 != 0) || 1509 ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0)); 1510 1511 if (f->ftcc.i == 0) { 1512 p_t = (f->f3.rs2 != 0 || p_rs1 == 0); 1513 1514 bprintf(dhp, "%-9s %s%s%s%s%s", inp->in_data.in_def.in_name, 1515 (v9 != 0) ? icc_names[f->ftcc2.cc] : "", 1516 (v9 != 0) ? ", " : "", 1517 (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "", 1518 (p_rs1 != 0) ? " + " : "", 1519 (p_t != 0) ? reg_names[f->f3.rs2] : ""); 1520 } else { 1521 bprintf(dhp, "%-9s %s%s%s%s0x%x", inp->in_data.in_def.in_name, 1522 (v9 != 0) ? icc_names[f->ftcc2.cc] : "", 1523 (v9 != 0) ? ", " : "", 1524 (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "", 1525 (p_rs1 != 0) ? " + " : "", 1526 f->ftcc.immtrap); 1527 } 1528 return (0); 1529 } 1530 1531 static int 1532 prt_shift(dis_handle_t *dhp, uint32_t instr, const inst_t *inp) 1533 { 1534 char name[5]; 1535 uint32_t cnt; 1536 1537 ifmt_t *f = (ifmt_t *)&instr; 1538 int octal = ((dhp->dh_flags & DIS_OCTAL) != 0); 1539 1540 name[0] = '\0'; 1541 (void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name)); 1542 1543 if (f->f3b.i == 1) 1544 cnt = f->f3.rs2; 1545 1546 if (f->f3b.x == 1 && ((dhp->dh_flags & DIS_SPARC_V8) == 0)) { 1547 cnt = f->f3b.shcnt; 1548 (void) strlcat(name, "x", sizeof (name)); 1549 } 1550 1551 prt_name(dhp, name, 1); 1552 1553 if (f->f3b.i == 1) 1554 bprintf(dhp, (octal != 0) ? "%s, 0%lo, %s" : "%s, 0x%lx, %s", 1555 reg_names[f->f3.rs1], cnt, reg_names[f->f3.rd]); 1556 else 1557 bprintf(dhp, "%s, %s, %s", reg_names[f->f3.rs1], 1558 reg_names[f->f3.rs2], reg_names[f->f3.rd]); 1559 1560 return (0); 1561 } 1562 1563 /* ARGSUSED3 */ 1564 static int 1565 prt_jmpl(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1566 { 1567 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 1568 const char *name = inp->in_data.in_def.in_name; 1569 ifmt_t *f = (ifmt_t *)&instr; 1570 1571 if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)) 1572 name = "call"; 1573 1574 if (f->f3.rd == 0) { 1575 if (f->f3.i == 1 && f->f3a.simm13 == 8) { 1576 if (f->f3.rs1 == 15) { 1577 prt_name(dhp, "retl", 0); 1578 return (0); 1579 } 1580 1581 if (f->f3.rs1 == 31) { 1582 prt_name(dhp, "ret", 0); 1583 return (0); 1584 } 1585 } 1586 1587 name = "jmp"; 1588 } 1589 1590 prt_name(dhp, name, 1); 1591 prt_address(dhp, instr, 1); 1592 1593 if (f->f3.rd == 0) 1594 return (0); 1595 1596 if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)) 1597 return (0); 1598 1599 bprintf(dhp, ", %s", reg_names[f->f3.rd]); 1600 1601 return (0); 1602 } 1603 1604 int 1605 fmt_alu(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1606 { 1607 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 1608 ifmt_t *f = (ifmt_t *)&instr; 1609 1610 const char *name = inp->in_data.in_def.in_name; 1611 int flags = inp->in_data.in_def.in_flags; 1612 int arg = 0; 1613 1614 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) { 1615 prt_field("op", f->f3.op, 2); 1616 prt_field("op3", f->f3.op3, 6); 1617 prt_field("rs1", f->f3.rs1, 5); 1618 1619 switch (idx) { 1620 /* TODO: more formats */ 1621 1622 default: 1623 if (f->f3.i == 0) 1624 prt_field("rs2", f->f3.rs2, 5); 1625 else 1626 prt_field("simm13", f->f3a.simm13, 13); 1627 1628 prt_field("rd", f->f3.rd, 5); 1629 } 1630 1631 } 1632 1633 switch (idx) { 1634 case 0x00: 1635 /* add */ 1636 1637 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0) 1638 break; 1639 1640 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1641 f->f3a.simm13 == 1) { 1642 name = "inc"; 1643 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1644 break; 1645 } 1646 1647 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1648 f->f3a.simm13 != 1) { 1649 name = "inc"; 1650 flags = FLG_P1(REG_NONE); 1651 break; 1652 } 1653 break; 1654 1655 case 0x02: 1656 /* or */ 1657 1658 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1659 == 0) 1660 break; 1661 1662 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) != 0) { 1663 if (f->f3.rs1 == f->f3.rd) { 1664 name = "bset"; 1665 flags = FLG_P1(REG_NONE); 1666 break; 1667 } 1668 } 1669 1670 if (((f->f3.i == 0 && f->f3.rs2 == 0) || 1671 (f->f3.i == 1 && f->f3a.simm13 == 0)) && 1672 (f->f3.rs1 == 0)) { 1673 name = "clr"; 1674 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1675 break; 1676 } 1677 1678 if (f->f3.rs1 == 0) { 1679 name = "mov"; 1680 flags = FLG_P1(REG_NONE); 1681 break; 1682 } 1683 break; 1684 1685 case 0x04: 1686 /* sub */ 1687 1688 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1689 == 0) 1690 break; 1691 1692 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 == f->f3.rd) { 1693 name = "neg"; 1694 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE); 1695 break; 1696 } 1697 1698 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 != f->f3.rd) { 1699 name = "neg"; 1700 flags = FLG_P1(REG_NONE); 1701 break; 1702 } 1703 1704 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0) 1705 break; 1706 1707 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1708 f->f3a.simm13 == 1) { 1709 name = "dec"; 1710 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1711 break; 1712 } 1713 1714 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1715 f->f3a.simm13 != 1) { 1716 name = "dec"; 1717 flags = FLG_P1(REG_NONE); 1718 break; 1719 } 1720 break; 1721 1722 case 0x07: 1723 /* xnor */ 1724 1725 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1726 == 0) 1727 break; 1728 1729 /* 1730 * xnor -> not when you have: 1731 * xnor %rs1, 0x0 or %g0, %rd 1732 */ 1733 if ((f->f3.i == 0 && f->f3.rs2 != 0) || 1734 (f->f3.i == 1 && f->f3a.simm13 != 0)) 1735 break; 1736 1737 name = "not"; 1738 1739 if (f->f3.rs1 == f->f3.rd) 1740 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM| 1741 FLG_P3(REG_INT); 1742 else 1743 flags = FLG_P1(REG_INT)|FLG_P2(REG_NONE)|FLG_NOIMM| 1744 FLG_P3(REG_INT); 1745 1746 break; 1747 1748 case 0x10: 1749 /* addcc */ 1750 1751 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0) 1752 break; 1753 1754 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1755 f->f3a.simm13 == 1) { 1756 name = "inccc"; 1757 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1758 break; 1759 } 1760 1761 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1762 f->f3a.simm13 != 1) { 1763 name = "inccc"; 1764 flags = FLG_P1(REG_NONE); 1765 break; 1766 } 1767 break; 1768 1769 case 0x11: 1770 /* andcc */ 1771 1772 if (f->f3.rd != 0) 1773 break; 1774 1775 if ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) 1776 == 0) 1777 break; 1778 1779 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0) && 1780 ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0)) 1781 break; 1782 1783 name = "btst"; 1784 flags = FLG_P1(REG_NONE); 1785 f->f3.rd = f->f3.rs1; 1786 break; 1787 1788 case 0x12: 1789 /* orcc */ 1790 1791 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1792 == 0) 1793 break; 1794 1795 if (f->f3.rs1 == 0 && f->f3.rd == 0 && f->f3.i == 0) { 1796 name = "tst"; 1797 flags = FLG_P1(REG_NONE)|FLG_P3(REG_NONE); 1798 break; 1799 } 1800 1801 if (f->f3.rs2 == 0 && f->f3.rd == 0 && f->f3.i == 0) { 1802 name = "tst"; 1803 flags = FLG_P2(REG_NONE)|FLG_P3(REG_NONE); 1804 break; 1805 } 1806 1807 break; 1808 1809 case 0x14: 1810 /* subcc */ 1811 1812 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1813 == 0) 1814 break; 1815 1816 if (f->f3.rd == 0) { 1817 name = "cmp"; 1818 flags = FLG_P3(REG_NONE); 1819 break; 1820 } 1821 1822 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0) 1823 break; 1824 1825 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1826 f->f3a.simm13 == 1) { 1827 name = "deccc"; 1828 flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM; 1829 break; 1830 } 1831 1832 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 && 1833 f->f3a.simm13 != 1) { 1834 name = "deccc"; 1835 flags = FLG_P1(REG_NONE); 1836 break; 1837 } 1838 1839 break; 1840 1841 case 0x25: 1842 case 0x26: 1843 case 0x27: 1844 return (prt_shift(dhp, instr, inp)); 1845 1846 case 0x28: 1847 case 0x29: 1848 case 0x2a: 1849 case 0x2b: 1850 case 0x30: 1851 case 0x31: 1852 case 0x32: 1853 case 0x33: 1854 return (dis_fmt_rdwr(dhp, instr, inp, idx)); 1855 1856 case 0x36: 1857 case 0x37: 1858 /* NOTE: overlayed on v9 */ 1859 if ((dhp->dh_flags & DIS_SPARC_V8) != 0) 1860 return (fmt_cpop(dhp, instr, inp)); 1861 break; 1862 1863 case 0x38: 1864 /* jmpl */ 1865 return (prt_jmpl(dhp, instr, inp, idx)); 1866 1867 case 0x39: 1868 /* rett / return */ 1869 prt_name(dhp, name, 1); 1870 prt_address(dhp, instr, 1); 1871 return (0); 1872 1873 case 0x3b: 1874 /* flush */ 1875 prt_name(dhp, name, 1); 1876 prt_address(dhp, instr, 0); 1877 return (0); 1878 1879 case 0x3c: 1880 case 0x3d: 1881 /* save / restore */ 1882 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) 1883 == 0) 1884 break; 1885 1886 if (f->f3.rs1 != 0 || f->f3.rs2 != 0 || f->f3.rd != 0) 1887 break; 1888 1889 if (f->f3.i != 0 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0)) 1890 break; 1891 1892 prt_name(dhp, name, 0); 1893 return (0); 1894 } 1895 1896 if (FLG_P1_VAL(flags) != REG_NONE || FLG_P2_VAL(flags) != REG_NONE || 1897 FLG_P3_VAL(flags) != REG_NONE) 1898 arg = 1; 1899 1900 prt_name(dhp, name, (arg != 0)); 1901 prt_aluargs(dhp, instr, flags); 1902 1903 return (0); 1904 } 1905 1906 /* ARGSUSED1 */ 1907 int 1908 fmt_regwin(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1909 { 1910 prt_name(dhp, inp->in_data.in_def.in_name, 0); 1911 return (0); 1912 } 1913 1914 /* ARGSUSED1 */ 1915 int 1916 fmt_trap_ret(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1917 { 1918 ifmt_t *f = (ifmt_t *)&instr; 1919 prt_name(dhp, inp->in_data.in_def.in_name, 1); 1920 1921 if (f->f3.rd == 0xf) { 1922 /* jpriv */ 1923 prt_address(dhp, instr, 1); 1924 } 1925 1926 return (0); 1927 } 1928 1929 /* ARGSUSED3 */ 1930 int 1931 fmt_movcc(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1932 { 1933 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 1934 ifmt_t *f = (ifmt_t *)&instr; 1935 const char **regs = NULL; 1936 1937 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) { 1938 prt_field("op", f->f3c.op, 2); 1939 prt_field("op3", f->f3c.op3, 6); 1940 prt_field("cond", f->f3c.cond, 4); 1941 prt_field("cc2", f->f3c.cc2, 1); 1942 prt_field("cc", f->f3c.cc, 2); 1943 prt_field("i", f->f3c.i, 1); 1944 1945 if (f->f3c.i == 0) 1946 prt_field("rs2", f->f3.rs2, 5); 1947 else 1948 prt_field("simm11", f->f3c.simm11, 11); 1949 1950 prt_field("rd", f->f3.rd, 5); 1951 } 1952 1953 if (f->f3c.cc2 == 0) { 1954 regs = fcc_names; 1955 } else { 1956 regs = icc_names; 1957 if (regs[f->f3c.cc] == NULL) 1958 return (-1); 1959 } 1960 1961 prt_name(dhp, inp->in_data.in_def.in_name, 1); 1962 1963 bprintf(dhp, "%s, ", regs[f->f3c.cc]); 1964 1965 if (f->f3c.i == 1) 1966 prt_imm(dhp, sign_extend(f->f3c.simm11, 11), IMM_SIGNED); 1967 else 1968 (void) strlcat(dhx->dhx_buf, reg_names[f->f3.rs2], 1969 dhx->dhx_buflen); 1970 1971 bprintf(dhp, ", %s", reg_names[f->f3.rd]); 1972 1973 return (0); 1974 } 1975 1976 /* ARGSUSED3 */ 1977 int 1978 fmt_movr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 1979 { 1980 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 1981 ifmt_t *f = (ifmt_t *)&instr; 1982 1983 prt_name(dhp, inp->in_data.in_def.in_name, 1); 1984 1985 bprintf(dhp, "%s, ", reg_names[f->f3d.rs1]); 1986 1987 if (f->f3d.i == 1) 1988 prt_imm(dhp, sign_extend(f->f3d.simm10, 10), IMM_SIGNED); 1989 else 1990 (void) strlcat(dhx->dhx_buf, reg_names[f->f3.rs2], 1991 dhx->dhx_buflen); 1992 1993 bprintf(dhp, ", %s", reg_names[f->f3.rd]); 1994 1995 return (0); 1996 } 1997 1998 /* ARGSUSED3 */ 1999 int 2000 fmt_fpop1(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2001 { 2002 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 2003 ifmt_t *f = (ifmt_t *)&instr; 2004 int flags = inp->in_data.in_def.in_flags; 2005 2006 flags |= FLG_NOIMM; 2007 2008 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) { 2009 prt_field("op", f->f3.op, 2); 2010 prt_field("op3", f->f3.op3, 6); 2011 prt_field("opf", f->fcmp.opf, 9); 2012 prt_field("rs1", f->f3.rs1, 5); 2013 prt_field("rs2", f->f3.rs2, 5); 2014 prt_field("rd", f->f3.rd, 5); 2015 } 2016 2017 prt_name(dhp, inp->in_data.in_def.in_name, 1); 2018 prt_aluargs(dhp, instr, flags); 2019 2020 return (0); 2021 } 2022 2023 int 2024 fmt_fpop2(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2025 { 2026 static const char *condstr_icc[16] = { 2027 "n", "e", "le", "l", "leu", "lu", "neg", "vs", 2028 "a", "nz", "g", "ge", "gu", "geu", "pos", "vc" 2029 }; 2030 2031 static const char *condstr_fcc[16] = { 2032 "n", "nz", "lg", "ul", "l", "ug", "g", "u", 2033 "a", "e", "ue", "ge", "uge", "le", "ule", "o" 2034 }; 2035 2036 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 2037 ifmt_t *f = (ifmt_t *)&instr; 2038 const char *ccstr = ""; 2039 char name[15]; 2040 2041 int flags = inp->in_data.in_def.in_flags; 2042 int is_cmp = (idx == 0x51 || idx == 0x52 || idx == 0x53 || 2043 idx == 0x55 || idx == 0x56 || idx == 0x57); 2044 int is_fmov = (idx & 0x3f); 2045 int is_v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0); 2046 int is_compat = ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0); 2047 2048 int p_cc = 0; 2049 2050 is_fmov = (is_fmov == 0x1 || is_fmov == 0x2 || is_fmov == 0x3); 2051 2052 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) { 2053 prt_field("op", f->f3.op, 2); 2054 prt_field("op3", f->f3.op3, 6); 2055 prt_field("opf", f->fcmp.opf, 9); 2056 2057 switch (idx & 0x3f) { 2058 case 0x51: 2059 case 0x52: 2060 case 0x53: 2061 case 0x55: 2062 case 0x56: 2063 case 0x57: 2064 prt_field("cc", f->fcmp.cc, 2); 2065 prt_field("rs1", f->f3.rs1, 5); 2066 prt_field("rs2", f->f3.rs2, 5); 2067 break; 2068 2069 case 0x01: 2070 case 0x02: 2071 case 0x03: 2072 prt_field("opf_low", f->fmv.opf, 6); 2073 prt_field("cond", f->fmv.cond, 4); 2074 prt_field("opf_cc", f->fmv.cc, 3); 2075 prt_field("rs2", f->fmv.rs2, 5); 2076 break; 2077 2078 default: 2079 prt_field("rs1", f->f3.rs1, 5); 2080 prt_field("rs2", f->f3.rs2, 5); 2081 prt_field("rd", f->f3.rd, 5); 2082 } 2083 } 2084 2085 name[0] = '\0'; 2086 (void) strlcat(name, inp->in_data.in_def.in_name, sizeof (name)); 2087 2088 if (is_fmov != 0) { 2089 (void) strlcat(name, 2090 (f->fmv.cc < 4) ? condstr_fcc[f->fmv.cond] 2091 : condstr_icc[f->fmv.cond], 2092 sizeof (name)); 2093 } 2094 2095 prt_name(dhp, name, 1); 2096 2097 if (is_cmp != 0) 2098 ccstr = fcc_names[f->fcmp.cc]; 2099 2100 if (is_fmov != 0) 2101 ccstr = (f->fmv.cc < 4) ? fcc_names[f->fmv.cc & 0x3] 2102 : icc_names[f->fmv.cc & 0x3]; 2103 2104 if (ccstr == NULL) 2105 return (-1); 2106 2107 p_cc = (is_compat == 0 || is_v9 != 0 || 2108 (is_cmp != 0 && f->fcmp.cc != 0) || 2109 (is_fmov != 0 && f->fmv.cc != 0)); 2110 2111 if (p_cc != 0) 2112 bprintf(dhp, "%s, ", ccstr); 2113 2114 prt_aluargs(dhp, instr, flags); 2115 2116 return (0); 2117 } 2118 2119 int 2120 fmt_vis(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2121 { 2122 dis_handle_sparc_t *dhx = dhp->dh_arch_private; 2123 ifmt_t *f = (ifmt_t *)&instr; 2124 int flags = inp->in_data.in_def.in_flags; 2125 2126 if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) { 2127 prt_field("op", f->f3.op, 2); 2128 prt_field("op3", f->f3.op3, 6); 2129 prt_field("opf", f->fcmp.opf, 9); 2130 2131 if (idx == 0x081) { 2132 prt_field("mode", instr & 02L, 2); 2133 } else { 2134 prt_field("rs1", f->f3.rs1, 5); 2135 prt_field("rs2", f->f3.rs2, 5); 2136 prt_field("rd", f->f3.rd, 5); 2137 } 2138 } 2139 2140 prt_name(dhp, inp->in_data.in_def.in_name, 1); 2141 2142 if (idx == 0x081) { 2143 /* siam */ 2144 bprintf(dhp, "%d", instr & 0x7L); 2145 return (0); 2146 } 2147 2148 prt_aluargs(dhp, instr, flags); 2149 2150 return (0); 2151 } 2152 2153 /* ARGSUSED3 */ 2154 int 2155 fmt_fused(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx) 2156 { 2157 ifmt_t *f = (ifmt_t *)&instr; 2158 int flags = inp->in_data.in_def.in_flags; 2159 2160 prt_name(dhp, inp->in_data.in_def.in_name, 1); 2161 bprintf(dhp, "%s, %s, %s, %s", 2162 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs1), 2163 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs2), 2164 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rs3), 2165 get_regname(dhp, FLG_P1_VAL(flags), f->fused.rd)); 2166 2167 return (0); 2168 } 2169 /* 2170 * put name into the output buffer 2171 * if add_space !=0, append a space after it 2172 */ 2173 static void 2174 prt_name(dis_handle_t *dhp, const char *name, int add_space) 2175 { 2176 bprintf(dhp, (add_space == 0) ? "%s" : "%-9s ", name); 2177 } 2178 2179 /* 2180 * For debugging, print out a field of the instruction 2181 * field is the name of the field 2182 * val is the value of the field 2183 * len is the length of the field (in bits) 2184 */ 2185 #if defined(DIS_STANDALONE) 2186 /* ARGSUSED */ 2187 static void 2188 prt_field(const char *field, uint32_t val, int len) 2189 { 2190 2191 } 2192 2193 #else 2194 static void 2195 prt_field(const char *field, uint32_t val, int len) 2196 { 2197 (void) fprintf(stderr, "DISASM: %8s = 0x%-8x (", field, val); 2198 prt_binary(val, len); 2199 (void) fprintf(stderr, ")\n"); 2200 } 2201 #endif /* DIS_STANDALONE */ 2202 2203 /* 2204 * sign extend a val (that is 'bits' bits in length) to a 32-bit signed 2205 * integer 2206 */ 2207 static int32_t 2208 sign_extend(int32_t val, int32_t bits) 2209 { 2210 if ((val & (1L << (bits - 1))) == 0) 2211 return (val); 2212 2213 return ((-1L << bits) | val); 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) vsnprintf(dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen, fmt, 2772 ap); 2773 va_end(ap); 2774 }