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