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 } 2773