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