Print this page
patch fix-lint
3317 dis(1) should support cross-target disassembly


  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  */
  31 
  32 
  33 #include <sys/byteorder.h>
  34 #include <stdarg.h>
  35 
  36 #if !defined(DIS_STANDALONE)
  37 #include <stdio.h>
  38 #endif /* DIS_STANDALONE */
  39 
  40 #include "libdisasm.h"
  41 #include "libdisasm_impl.h"
  42 #include "dis_sparc.h"
  43 #include "dis_sparc_fmt.h"
  44 
  45 extern char *strncpy(char *, const char *, size_t);
  46 extern size_t strlen(const char *);
  47 extern int strcmp(const char *, const char *);
  48 extern int strncmp(const char *, const char *, size_t);
  49 extern size_t strlcat(char *, const char *, size_t);
  50 extern size_t strlcpy(char *, const char *, size_t);
  51 extern int snprintf(char *, size_t, const char *, ...);
  52 extern int vsnprintf(char *, size_t, const char *, va_list);
  53 
  54 /*
  55  * This file has the functions that do all the dirty work of outputting the
  56  * disassembled instruction
  57  *
  58  * All the non-static functions follow the format_fcn (in dis_sparc.h):
  59  * Input:
  60  *      disassembler handle/context
  61  *      instruction to disassemble
  62  *      instruction definition pointer (inst_t *)
  63  *      index in the table of the instruction
  64  * Return:
  65  *      0 Success
  66  *    !0 Invalid instruction
  67  *
  68  * Generally, instructions found in the same table use the same output format
  69  * or have a few minor differences (which are described in the 'flags' field
  70  * of the instruction definition. In some cases, certain instructions differ
  71  * radically enough from those in the same table, that their own format
  72  * function is used.


 681         int i;
 682 
 683         for (i = bitlen - 1; i >= 0; --i) {
 684                 (void) fprintf(stderr, ((val & (1L << i)) != 0) ? "1" : "0");
 685 
 686                 if (i % 4 == 0 && i != 0)
 687                         (void) fprintf(stderr, " ");
 688         }
 689 }
 690 #endif /* DIS_STANDALONE */
 691 
 692 
 693 /*
 694  * print out a call instruction
 695  * format: call address  <name>
 696  */
 697 /* ARGSUSED1 */
 698 int
 699 fmt_call(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
 700 {

 701         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 ((dhp->dh_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(dhp->dh_buf, " <", dhp->dh_buflen);
 722 
 723         curlen = strlen(dhp->dh_buf);
 724         dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
 725             dhp->dh_buf + curlen, dhp->dh_buflen - curlen - 1, NULL,
 726             NULL);
 727         (void) strlcat(dhp->dh_buf, ">", dhp->dh_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         ifmt_t *f = (ifmt_t *)&instr;
 737 
 738         if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
 739                 prt_field("op", f->f2.op, 2);
 740                 prt_field("op2", f->f2.op2, 3);
 741                 prt_field("rd", f->f2.rd, 5);
 742                 prt_field("imm22", f->f2.imm22, 22);
 743         }
 744 
 745         if (idx == 0) {
 746                 /* unimp / illtrap */
 747                 prt_name(dhp, inp->in_data.in_def.in_name, 1);
 748                 prt_imm(dhp, f->f2.imm22, 0);
 749                 return (0);
 750         }
 751 
 752         if (f->f2.imm22 == 0 && f->f2.rd == 0) {
 753                 prt_name(dhp, "nop", 0);
 754                 return (0);
 755         }
 756 
 757         /* ?? Should we return -1 if rd == 0 && disp != 0 */
 758 
 759         prt_name(dhp, inp->in_data.in_def.in_name, 1);
 760 
 761         bprintf(dhp,
 762             ((dhp->dh_flags & DIS_OCTAL) != 0) ?
 763             "%%hi(0%lo), %s" : "%%hi(0x%lx), %s",
 764             f->f2.imm22 << 10,
 765             reg_names[f->f2.rd]);
 766 
 767         return (0);
 768 }
 769 
 770 /* ARGSUSED3 */
 771 int
 772 fmt_branch(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
 773 {

 774         const char *name = inp->in_data.in_def.in_name;
 775         const char *r = NULL;
 776         const char *annul = "";
 777         const char *pred  = "";
 778 
 779         char buf[15];
 780 
 781         ifmt_t *f = (ifmt_t *)&instr;
 782 
 783         size_t curlen;
 784         int32_t disp;
 785         uint32_t flags = inp->in_data.in_def.in_flags;
 786         int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
 787 
 788         if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
 789                 prt_field("op", f->f2.op, 2);
 790                 prt_field("op2", f->f2.op2, 3);
 791 
 792                 switch (FLG_DISP_VAL(flags)) {
 793                 case DISP22:
 794                         prt_field("cond", f->f2a.cond, 4);
 795                         prt_field("a", f->f2a.a, 1);
 796                         prt_field("disp22", f->f2a.disp22, 22);
 797                         break;
 798 
 799                 case DISP19:
 800                         prt_field("cond", f->f2a.cond, 4);
 801                         prt_field("a", f->f2a.a, 1);
 802                         prt_field("p", f->f2b.p, 1);
 803                         prt_field("cc", f->f2b.cc, 2);
 804                         prt_field("disp19", f->f2b.disp19, 19);
 805                         break;
 806 
 807                 case DISP16:
 808                         prt_field("bit 28", ((instr & (1L << 28)) >> 28), 1);
 809                         prt_field("rcond", f->f2c.cond, 3);
 810                         prt_field("p", f->f2c.p, 1);
 811                         prt_field("rs1", f->f2c.rs1, 5);
 812                         prt_field("d16hi", f->f2c.d16hi, 2);
 813                         prt_field("d16lo", f->f2c.d16lo, 14);
 814                         break;
 815                 }
 816         }
 817 
 818         if (f->f2b.op2 == 0x01 && idx == 0x00 && f->f2b.p == 1 &&
 819             f->f2b.cc == 0x02 && ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) != 0)) {
 820                 name = "iprefetch";
 821                 flags = FLG_RS1(REG_NONE)|FLG_DISP(DISP19);
 822         }
 823 
 824 
 825         switch (FLG_DISP_VAL(flags)) {
 826         case DISP22:
 827                 disp = sign_extend(f->f2a.disp22, 22);
 828                 break;
 829 
 830         case DISP19:
 831                 disp = sign_extend(f->f2b.disp19, 19);
 832                 break;
 833 
 834         case DISP16:
 835                 disp = sign_extend((f->f2c.d16hi << 14)|f->f2c.d16lo, 16);
 836                 break;
 837 
 838         }
 839 
 840         disp *= 4;
 841 
 842         if ((FLG_RS1_VAL(flags) == REG_ICC) || (FLG_RS1_VAL(flags) == REG_FCC))
 843                 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2b.cc);
 844         else
 845                 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2c.rs1);
 846 
 847         if (r == NULL)
 848                 return (-1);
 849 
 850         if (f->f2a.a == 1)
 851                 annul = ",a";
 852 
 853         if ((flags & FLG_PRED) != 0) {
 854                 if (f->f2b.p == 0) {
 855                         pred = ",pn";
 856                 } else {
 857                         if ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0)
 858                                 pred = ",pt";
 859                 }
 860         }
 861 
 862         (void) snprintf(buf, sizeof (buf), "%s%s%s", name, annul, pred);
 863         prt_name(dhp, buf, 1);
 864 
 865 
 866         switch (FLG_DISP_VAL(flags)) {
 867         case DISP22:
 868                 bprintf(dhp,
 869                     (octal != 0) ? "%s0%-11lo <" : "%s0x%-10lx <",
 870                     (disp < 0) ? "-" : "+",
 871                     (disp < 0) ? (-disp) : disp);
 872                 break;
 873 
 874         case DISP19:
 875                 bprintf(dhp,
 876                     (octal != 0) ? "%s, %s0%-5lo <" :
 877                     "%s, %s0x%-04lx <", r,
 878                     (disp < 0) ? "-" : "+",
 879                     (disp < 0) ? (-disp) : disp);
 880                 break;
 881 
 882         case DISP16:
 883                 bprintf(dhp,
 884                     (octal != 0) ? "%s, %s0%-6lo <" : "%s, %s0x%-5lx <",
 885                     r,
 886                     (disp < 0) ? "-" : "+",
 887                     (disp < 0) ? (-disp) : disp);
 888                 break;
 889         }
 890 
 891         curlen = strlen(dhp->dh_buf);
 892         dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
 893             dhp->dh_buf + curlen, dhp->dh_buflen - curlen - 1, NULL, NULL);
 894 
 895         (void) strlcat(dhp->dh_buf, ">", dhp->dh_buflen);
 896 
 897         return (0);
 898 }
 899 
 900 
 901 
 902 /*
 903  * print out the compare and swap instructions (casa/casxa)
 904  * format: casa/casxa [%rs1] imm_asi, %rs2, %rd
 905  *          casa/casxa [%rs1] %asi, %rs2, %rd
 906  *
 907  * If DIS_DEBUG_SYN_ALL is set, synthetic instructions are emitted
 908  * when an immediate ASI value is given as follows:
 909  *
 910  * casa  [%rs1]#ASI_P, %rs2, %rd    -> cas   [%rs1], %rs2, %rd
 911  * casa  [%rs1]#ASI_P_L, %rs2, %rd  -> casl  [%rs1], %rs2, %rd
 912  * casxa [%rs1]#ASI_P, %rs2, %rd    -> casx  [%rs1], %rs2, %rd
 913  * casxa [%rs1]#ASI_P_L, %rs2, %rd  -> casxl [%rs1], %rs2, %rd
 914  */
 915 static int
 916 fmt_cas(dis_handle_t *dhp, uint32_t instr, const char *name)
 917 {

 918         ifmt_t *f = (ifmt_t *)&instr;
 919         const char *asistr = NULL;
 920         int noasi = 0;
 921 
 922         asistr = get_asi_name(f->f3.asi);
 923 
 924         if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) != 0) {
 925                 if (f->f3.op3 == 0x3c && f->f3.i == 0) {
 926                         if (f->f3.asi == 0x80) {
 927                                 noasi = 1;
 928                                 name = "cas";
 929                         }
 930 
 931                         if (f->f3.asi == 0x88) {
 932                                 noasi = 1;
 933                                 name = "casl";
 934                         }
 935                 }
 936 
 937                 if (f->f3.op3 == 0x3e && f->f3.i == 0) {
 938                         if (f->f3.asi == 0x80) {
 939                                 noasi = 1;
 940                                 name = "casx";
 941                         }
 942 
 943                         if (f->f3.asi == 0x88) {
 944                                 noasi = 1;
 945                                 name = "casxl";
 946                         }
 947                 }
 948         }
 949 
 950         prt_name(dhp, name, 1);
 951 
 952         bprintf(dhp, "[%s]", reg_names[f->f3.rs1]);
 953 
 954         if (noasi == 0) {
 955                 (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen);
 956                 prt_asi(dhp, instr);
 957         }
 958 
 959         bprintf(dhp, ", %s, %s", reg_names[f->f3.rs2], reg_names[f->f3.rd]);
 960 
 961         if (noasi == 0 && asistr != NULL)
 962                 bprintf(dhp, "\t<%s>", asistr);
 963 
 964         return (0);
 965 }
 966 
 967 /*
 968  * format a load/store instruction
 969  * format: ldXX [%rs1 + %rs2], %rd        load, i==0
 970  *          ldXX [%rs1 +/- nn], %rd       load, i==1
 971  *          ldXX [%rs1 + %rs2] #XX, %rd   load w/ imm_asi, i==0
 972  *          ldXX [%rs1 +/- nn] %asi, %rd  load from asi[%asi], i==1
 973  *
 974  *          stXX %rd, [%rs1 + %rs2]       store, i==0
 975  *          stXX %rd, [%rs1 +/- nn]       store, i==1


 982  * If DIS_DEBUG_SYNTH_ALL or DIS_DEBUG_COMPAT are set,
 983  * When %rs1, %rs2 or nn are 0, they are not printed, i.e.
 984  * [ %rs1 + 0x0 ], %rd -> [%rs1], %rd for example
 985  *
 986  * The following synthetic instructions are also implemented:
 987  *
 988  * stb %g0, [addr] -> clrb [addr]    DIS_DEBUG_SYNTH_ALL
 989  * sth %g0, [addr] -> crlh [addr]    DIS_DEBUG_SYNTH_ALL
 990  * stw %g0, [addr] -> clr  [addr]    DIS_DEBUG_SYNTH_ALL|DIS_DEBUG_COMPAT
 991  * stx %g0, [addr] -> clrx [addr]    DIS_DEBUG_SYNTH_ALL
 992  *
 993  * If DIS_DEBUG_COMPAT is set, the following substitutions also take place
 994  *      lduw -> ld
 995  *      ldtw -> ld
 996  *      stuw -> st
 997  *      sttw -> st
 998  */
 999 int
1000 fmt_ls(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1001 {

1002         ifmt_t *f = (ifmt_t *)&instr;
1003         const char *regstr = NULL;
1004         const char *asistr = NULL;
1005 
1006         const char *iname = inp->in_data.in_def.in_name;
1007         uint32_t flags = inp->in_data.in_def.in_flags;
1008 
1009         if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
1010                 prt_field("op", f->f3.op, 2);
1011                 prt_field("op3", f->f3.op3, 6);
1012                 prt_field("rs1", f->f3.rs1, 5);
1013                 prt_field("i", f->f3.i, 1);
1014                 if (f->f3.i != 0) {
1015                         prt_field("simm13", f->f3a.simm13, 13);
1016                 } else {
1017                         if ((flags & FLG_ASI) != 0)
1018                                 prt_field("imm_asi", f->f3.asi, 8);
1019                         prt_field("rs2", f->f3.rs2, 5);
1020                 }
1021                 prt_field("rd", f->f3.rd, 5);
1022         }
1023 
1024         if (idx == 0x2d || idx == 0x3d) {
1025                 /* prefetch / prefetcha */
1026 
1027                 prt_name(dhp, iname, 1);
1028 
1029                 prt_address(dhp, instr, 0);
1030 
1031                 if (idx == 0x3d) {
1032                         (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen);
1033                         prt_asi(dhp, instr);
1034                 }
1035 
1036                 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
1037 
1038                 /* fcn field is the same as rd */
1039                 if (prefetch_str[f->f3.rd] != NULL)
1040                         (void) strlcat(dhp->dh_buf, prefetch_str[f->f3.rd],
1041                             dhp->dh_buflen);
1042                 else
1043                         prt_imm(dhp, f->f3.rd, 0);
1044 
1045                 if (idx == 0x3d && f->f3.i == 0) {
1046                         asistr = get_asi_name(f->f3.asi);
1047                         if (asistr != NULL)
1048                                 bprintf(dhp, "\t<%s>", asistr);
1049                 }
1050 
1051                 return (0);
1052         }
1053 
1054         /* casa / casxa */
1055         if (idx == 0x3c || idx == 0x3e)
1056                 return (fmt_cas(dhp, instr, iname));
1057 
1058         /* synthetic instructions & special cases */
1059         switch (idx) {
1060         case 0x00:
1061                 /* ld */
1062                 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)
1063                         iname = "lduw";
1064                 break;
1065 
1066         case 0x03:
1067                 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)
1068                         iname = "ldtw";
1069                 break;
1070 
1071         case 0x04:
1072                 /* stw */
1073                 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)
1074                         iname = "stuw";
1075 
1076                 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1077                     == 0)
1078                         break;
1079 
1080                 if (f->f3.rd == 0) {
1081                         iname = "clr";
1082                         flags = FLG_RD(REG_NONE);
1083                 }
1084                 break;
1085 
1086         case 0x05:
1087                 /* stb */
1088                 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1089                     == 0)
1090                         break;
1091 
1092                 if (f->f3.rd == 0) {
1093                         iname = "clrb";
1094                         flags = FLG_RD(REG_NONE);
1095                 }
1096                 break;
1097 
1098         case 0x06:
1099                 /* sth */
1100                 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1101                     == 0)
1102                         break;
1103 
1104                 if (f->f3.rd == 0) {
1105                         iname = "clrh";
1106                         flags = FLG_RD(REG_NONE);
1107                 }
1108                 break;
1109 
1110         case 0x07:
1111                 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)
1112                         iname = "sttw";
1113                 break;
1114 
1115         case 0x0e:
1116                 /* stx */
1117 
1118                 if ((dhp->dh_flags & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1119                     == 0)
1120                         break;
1121 
1122                 if (f->f3.rd == 0) {
1123                         iname = "clrx";
1124                         flags = FLG_RD(REG_NONE);
1125                 }
1126                 break;
1127 
1128         case 0x13:
1129                 /* ldtwa */
1130                 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) &&
1131                     ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
1132                         iname = "ldtwa";
1133                 break;
1134 
1135         case 0x17:
1136                 /* sttwa */
1137                 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) &&
1138                     ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
1139                         iname = "sttwa";
1140                 break;
1141 
1142         case 0x21:
1143         case 0x25:
1144                 /*
1145                  * on sparcv8 it merely says that rd != 1 should generate an
1146                  * exception, on v9, it is illegal
1147                  */
1148                 if ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0)
1149                         break;
1150 
1151                 iname = (idx == 0x21) ? "ldx" : "stx";
1152 
1153                 if (f->f3.rd > 1)
1154                         return (-1);
1155 
1156                 break;
1157 


1195                                 if (asistr != NULL)
1196                                         bprintf(dhp, "\t<%s>", asistr);
1197 
1198                                 return (0);
1199 
1200                         default:
1201                                 break;
1202                 }
1203 
1204         }
1205 
1206         regstr = get_regname(dhp, FLG_RD_VAL(flags), f->f3.rd);
1207 
1208         if (f->f3.i == 0)
1209                 asistr = get_asi_name(f->f3.asi);
1210 
1211         prt_name(dhp, iname, 1);
1212 
1213         if ((flags & FLG_STORE) != 0) {
1214                 if (regstr[0] != '\0') {
1215                         (void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen);
1216                         (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
1217                 }
1218 
1219                 prt_address(dhp, instr, 0);
1220                 if ((flags & FLG_ASI) != 0) {
1221                         (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen);
1222                         prt_asi(dhp, instr);
1223                 }
1224         } else {
1225                 prt_address(dhp, instr, 0);
1226                 if ((flags & FLG_ASI) != 0) {
1227                         (void) strlcat(dhp->dh_buf, " ", dhp->dh_buflen);
1228                         prt_asi(dhp, instr);
1229                 }
1230 
1231                 if (regstr[0] != '\0') {
1232                         (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
1233                         (void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen);
1234                 }
1235         }
1236 
1237         if ((flags & FLG_ASI) != 0 && asistr != NULL)
1238                 bprintf(dhp, "\t<%s>", asistr);
1239 
1240         return (0);
1241 }
1242 
1243 static int
1244 fmt_cpop(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1245 {

1246         ifmt_t *f = (ifmt_t *)&instr;
1247         int flags = FLG_P1(REG_CP)|FLG_P2(REG_CP)|FLG_NOIMM|FLG_P3(REG_CP);
1248 
1249         if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
1250                 prt_field("op", f->fcp.op, 2);
1251                 prt_field("op3", f->fcp.op3, 6);
1252                 prt_field("opc", f->fcp.opc, 9);
1253                 prt_field("rs1", f->fcp.rs1, 5);
1254                 prt_field("rs2", f->fcp.rs2, 5);
1255                 prt_field("rd", f->fcp.rd, 5);
1256         }
1257 
1258         prt_name(dhp, inp->in_data.in_def.in_name, 1);
1259         prt_imm(dhp, f->fcp.opc, 0);
1260 
1261         (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
1262         (void) prt_aluargs(dhp, instr, flags);
1263 
1264         return (0);
1265 }
1266 
1267 static int
1268 dis_fmt_rdwr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1269 {

1270         const char *psr_str = "%psr";
1271         const char *wim_str = "%wim";
1272         const char *tbr_str = "%tbr";
1273 
1274         const char *name = inp->in_data.in_def.in_name;
1275         const char *regstr = NULL;
1276 
1277         ifmt_t *f = (ifmt_t *)&instr;
1278 
1279         int rd = (idx < 0x30);
1280         int v9 = (dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI));
1281         int ridx = f->f3.rs1;
1282         int i, first;
1283         int pr_rs1 = 1;
1284         int pr_rs2 = 1;
1285 
1286         int use_mask = 1;
1287         uint32_t mask;
1288 
1289         if (rd == 0)


1375                         mask = v9_asr_wrmask;
1376                 } else {
1377                         regstr = asr_names[ridx];
1378                         mask = asr_wrmask;
1379                 }
1380 
1381                 /*
1382                  * sir is shoehorned in here, per Ultrasparc 2007
1383                  * hyperprivileged edition, section 7.88, all of
1384                  * these must be true to distinguish from WRasr
1385                  */
1386                 if (v9 != 0 && f->f3.rd == 15 && f->f3.rs1 == 0 &&
1387                     f->f3.i == 1) {
1388                         prt_name(dhp, "sir", 1);
1389                         prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
1390                             IMM_SIGNED);
1391                         return (0);
1392                 }
1393 
1394                 /* synth: mov */
1395                 if ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1396                     == 0)
1397                         break;
1398 
1399                 if (v9 == 0) {
1400                         if (f->f3.rs1 == 0) {
1401                                 name = "mov";
1402                                 pr_rs1 = 0;
1403                         }
1404 
1405                         if ((f->f3.i == 0 && f->f3.rs2 == 0) ||
1406                             (f->f3.i == 1 && f->f3a.simm13 == 0)) {
1407                                 name = "mov";
1408                                 pr_rs2 = 0;
1409                         }
1410                 }
1411 
1412                 if (pr_rs1 == 0)
1413                         pr_rs2 = 1;
1414 
1415                 break;


1447 
1448         if (regstr == NULL)
1449                 return (-1);
1450 
1451         if (use_mask != 0 && ((1L << ridx) & mask) == 0)
1452                 return (-1);
1453 
1454         prt_name(dhp, name, 1);
1455 
1456         if (rd != 0) {
1457                 bprintf(dhp, "%s, %s", regstr, reg_names[f->f3.rd]);
1458         } else {
1459                 if (pr_rs1 == 1)
1460                         bprintf(dhp, "%s, ", reg_names[f->f3.rs1]);
1461 
1462                 if (pr_rs2 != 0) {
1463                         if (f->f3.i == 1)
1464                                 prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
1465                                     IMM_SIGNED);
1466                         else
1467                                 (void) strlcat(dhp->dh_buf,
1468                                     reg_names[f->f3.rs2], dhp->dh_buflen);
1469                         (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
1470                 }
1471 
1472                 (void) strlcat(dhp->dh_buf, regstr, dhp->dh_buflen);
1473         }
1474 
1475         return (0);
1476 }
1477 
1478 /* ARGSUSED3 */
1479 int
1480 fmt_trap(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1481 {

1482         ifmt_t *f = (ifmt_t *)&instr;
1483 
1484         int v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
1485         int p_rs1, p_t;
1486 
1487         if (f->ftcc.undef != 0)
1488                 return (-1);
1489 
1490         if (icc_names[f->ftcc.cc] == NULL)
1491                 return (-1);
1492 
1493         if (f->ftcc.i == 1 && f->ftcc.undef2 != 0)
1494                 return (-1);
1495 
1496         if (f->ftcc2.i == 0 && f->ftcc2.undef2 != 0)
1497                 return (-1);
1498 
1499         p_rs1 = ((f->ftcc.rs1 != 0) ||
1500             ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0));
1501 
1502         if (f->ftcc.i == 0) {
1503                 p_t = (f->f3.rs2 != 0 || p_rs1 == 0);
1504 
1505                 bprintf(dhp, "%-9s %s%s%s%s%s", inp->in_data.in_def.in_name,
1506                     (v9 != 0) ? icc_names[f->ftcc2.cc] : "",
1507                     (v9 != 0) ? ", " : "",
1508                     (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "",
1509                     (p_rs1 != 0) ? " + " : "",
1510                     (p_t != 0) ? reg_names[f->f3.rs2] : "");
1511         } else {
1512                 bprintf(dhp, "%-9s %s%s%s%s0x%x", 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                     f->ftcc.immtrap);
1518         }
1519         return (0);
1520 }


1538                 cnt = f->f3b.shcnt;
1539                 (void) strlcat(name, "x", sizeof (name));
1540         }
1541 
1542         prt_name(dhp, name, 1);
1543 
1544         if (f->f3b.i == 1)
1545                 bprintf(dhp, (octal != 0) ? "%s, 0%lo, %s" : "%s, 0x%lx, %s",
1546                     reg_names[f->f3.rs1], cnt, reg_names[f->f3.rd]);
1547         else
1548                 bprintf(dhp, "%s, %s, %s", reg_names[f->f3.rs1],
1549                     reg_names[f->f3.rs2], reg_names[f->f3.rd]);
1550 
1551         return (0);
1552 }
1553 
1554 /* ARGSUSED3 */
1555 static int
1556 prt_jmpl(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1557 {

1558         const char *name = inp->in_data.in_def.in_name;
1559         ifmt_t *f = (ifmt_t *)&instr;
1560 
1561         if (f->f3.rd == 15 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0))
1562                 name = "call";
1563 
1564         if (f->f3.rd == 0) {
1565                 if (f->f3.i == 1 && f->f3a.simm13 == 8) {
1566                         if (f->f3.rs1 == 15) {
1567                                 prt_name(dhp, "retl", 0);
1568                                 return (0);
1569                         }
1570 
1571                         if (f->f3.rs1 == 31) {
1572                                 prt_name(dhp, "ret", 0);
1573                                 return (0);
1574                         }
1575                 }
1576 
1577                 name = "jmp";
1578         }
1579 
1580         prt_name(dhp, name, 1);
1581         prt_address(dhp, instr, 1);
1582 
1583         if (f->f3.rd == 0)
1584                 return (0);
1585 
1586         if (f->f3.rd == 15 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0))
1587                 return (0);
1588 
1589         bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1590 
1591         return (0);
1592 }
1593 
1594 int
1595 fmt_alu(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1596 {

1597         ifmt_t *f = (ifmt_t *)&instr;
1598 
1599         const char *name = inp->in_data.in_def.in_name;
1600         int flags = inp->in_data.in_def.in_flags;
1601         int arg = 0;
1602 
1603         if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
1604                 prt_field("op", f->f3.op, 2);
1605                 prt_field("op3", f->f3.op3, 6);
1606                 prt_field("rs1", f->f3.rs1, 5);
1607 
1608                 switch (idx) {
1609                         /* TODO: more formats */
1610 
1611                 default:
1612                         if (f->f3.i == 0)
1613                                 prt_field("rs2", f->f3.rs2, 5);
1614                         else
1615                                 prt_field("simm13", f->f3a.simm13, 13);
1616 
1617                         prt_field("rd", f->f3.rd, 5);
1618                 }
1619 
1620         }
1621 
1622         switch (idx) {
1623         case 0x00:
1624                 /* add */
1625 
1626                 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0)
1627                         break;
1628 
1629                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1630                     f->f3a.simm13 == 1) {
1631                         name = "inc";
1632                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1633                         break;
1634                 }
1635 
1636                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1637                     f->f3a.simm13 != 1) {
1638                         name = "inc";
1639                         flags = FLG_P1(REG_NONE);
1640                         break;
1641                 }
1642                 break;
1643 
1644         case 0x02:
1645                 /* or */
1646 
1647                 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1648                     == 0)
1649                         break;
1650 
1651                 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) != 0) {
1652                         if (f->f3.rs1 == f->f3.rd) {
1653                                 name = "bset";
1654                                 flags = FLG_P1(REG_NONE);
1655                                 break;
1656                         }
1657                 }
1658 
1659                 if (((f->f3.i == 0 && f->f3.rs2 == 0) ||
1660                     (f->f3.i == 1 && f->f3a.simm13 == 0)) &&
1661                     (f->f3.rs1 == 0)) {
1662                         name = "clr";
1663                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1664                         break;
1665                 }
1666 
1667                 if (f->f3.rs1 == 0) {
1668                         name = "mov";
1669                         flags = FLG_P1(REG_NONE);
1670                         break;
1671                 }
1672                 break;
1673 
1674         case 0x04:
1675                 /* sub */
1676 
1677                 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1678                     == 0)
1679                         break;
1680 
1681                 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 == f->f3.rd) {
1682                         name = "neg";
1683                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE);
1684                         break;
1685                 }
1686 
1687                 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 != f->f3.rd) {
1688                         name = "neg";
1689                         flags = FLG_P1(REG_NONE);
1690                         break;
1691                 }
1692 
1693                 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0)
1694                         break;
1695 
1696                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1697                     f->f3a.simm13 == 1) {
1698                         name = "dec";
1699                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1700                         break;
1701                 }
1702 
1703                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1704                     f->f3a.simm13 != 1) {
1705                         name = "dec";
1706                         flags = FLG_P1(REG_NONE);
1707                         break;
1708                 }
1709                 break;
1710 
1711         case 0x07:
1712                 /* xnor */
1713 
1714                 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1715                     == 0)
1716                         break;
1717 
1718                 /*
1719                  * xnor -> not when you have:
1720                  *       xnor %rs1, 0x0 or %g0, %rd
1721                  */
1722                 if ((f->f3.i == 0 && f->f3.rs2 != 0) ||
1723                     (f->f3.i == 1 && f->f3a.simm13 != 0))
1724                         break;
1725 
1726                 name = "not";
1727 
1728                 if (f->f3.rs1 == f->f3.rd)
1729                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM|
1730                             FLG_P3(REG_INT);
1731                 else
1732                         flags = FLG_P1(REG_INT)|FLG_P2(REG_NONE)|FLG_NOIMM|
1733                             FLG_P3(REG_INT);
1734 
1735                 break;
1736 
1737         case 0x10:
1738                 /* addcc */
1739 
1740                 if ((dhp->dh_debug & DIS_DEBUG_SYN_ALL) == 0)
1741                         break;
1742 
1743                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1744                     f->f3a.simm13 == 1) {
1745                         name = "inccc";
1746                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1747                         break;
1748                 }
1749 
1750                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1751                     f->f3a.simm13 != 1) {
1752                         name = "inccc";
1753                         flags = FLG_P1(REG_NONE);
1754                         break;
1755                 }
1756                 break;
1757 
1758         case 0x11:
1759                 /* andcc */
1760 
1761                 if (f->f3.rd != 0)
1762                         break;
1763 
1764                 if ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1765                     == 0)
1766                         break;
1767 
1768                 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0) &&
1769                     ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0))
1770                         break;
1771 
1772                 name = "btst";
1773                 flags = FLG_P1(REG_NONE);
1774                 f->f3.rd = f->f3.rs1;
1775                 break;
1776 
1777         case 0x12:
1778                 /* orcc */
1779 
1780                 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1781                     == 0)
1782                         break;
1783 
1784                 if (f->f3.rs1 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1785                         name = "tst";
1786                         flags = FLG_P1(REG_NONE)|FLG_P3(REG_NONE);
1787                         break;
1788                 }
1789 
1790                 if (f->f3.rs2 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1791                         name = "tst";
1792                         flags = FLG_P2(REG_NONE)|FLG_P3(REG_NONE);
1793                         break;
1794                 }
1795 
1796                 break;
1797 
1798         case 0x14:
1799                 /* subcc */
1800 
1801                 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1802                     == 0)
1803                         break;
1804 
1805                 if (f->f3.rd == 0) {
1806                         name = "cmp";
1807                         flags = FLG_P3(REG_NONE);
1808                         break;
1809                 }
1810 
1811                 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0)
1812                         break;
1813 
1814                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1815                     f->f3a.simm13 == 1) {
1816                         name = "deccc";
1817                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1818                         break;
1819                 }
1820 
1821                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1822                     f->f3a.simm13 != 1) {
1823                         name = "deccc";
1824                         flags = FLG_P1(REG_NONE);
1825                         break;
1826                 }
1827 
1828                 break;
1829 
1830         case 0x25:
1831         case 0x26:


1851 
1852         case 0x38:
1853                 /* jmpl */
1854                 return (prt_jmpl(dhp, instr, inp, idx));
1855 
1856         case 0x39:
1857                 /* rett / return */
1858                 prt_name(dhp, name, 1);
1859                 prt_address(dhp, instr, 1);
1860                 return (0);
1861 
1862         case 0x3b:
1863                 /* flush */
1864                 prt_name(dhp, name, 1);
1865                 prt_address(dhp, instr, 0);
1866                 return (0);
1867 
1868         case 0x3c:
1869         case 0x3d:
1870                 /* save / restore */
1871                 if ((dhp->dh_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1872                     == 0)
1873                         break;
1874 
1875                 if (f->f3.rs1 != 0 || f->f3.rs2 != 0 || f->f3.rd != 0)
1876                         break;
1877 
1878                 if (f->f3.i != 0 && ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0))
1879                         break;
1880 
1881                 prt_name(dhp, name, 0);
1882                 return (0);
1883         }
1884 
1885         if (FLG_P1_VAL(flags) != REG_NONE || FLG_P2_VAL(flags) != REG_NONE ||
1886             FLG_P3_VAL(flags) != REG_NONE)
1887                 arg = 1;
1888 
1889         prt_name(dhp, name, (arg != 0));
1890         prt_aluargs(dhp, instr, flags);
1891 
1892         return (0);
1893 }
1894 
1895 /* ARGSUSED1 */
1896 int
1897 fmt_regwin(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1898 {


1902 
1903 /* ARGSUSED1 */
1904 int
1905 fmt_trap_ret(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1906 {
1907         ifmt_t *f = (ifmt_t *)&instr;
1908         prt_name(dhp, inp->in_data.in_def.in_name, 1);
1909 
1910         if (f->f3.rd == 0xf) {
1911                 /* jpriv */
1912                 prt_address(dhp, instr, 1);
1913         }
1914 
1915         return (0);
1916 }
1917 
1918 /* ARGSUSED3 */
1919 int
1920 fmt_movcc(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1921 {

1922         ifmt_t *f = (ifmt_t *)&instr;
1923         const char **regs = NULL;
1924 
1925         if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
1926                 prt_field("op", f->f3c.op, 2);
1927                 prt_field("op3", f->f3c.op3, 6);
1928                 prt_field("cond", f->f3c.cond, 4);
1929                 prt_field("cc2", f->f3c.cc2, 1);
1930                 prt_field("cc", f->f3c.cc, 2);
1931                 prt_field("i", f->f3c.i, 1);
1932 
1933                 if (f->f3c.i == 0)
1934                         prt_field("rs2", f->f3.rs2, 5);
1935                 else
1936                         prt_field("simm11", f->f3c.simm11, 11);
1937 
1938                 prt_field("rd", f->f3.rd, 5);
1939         }
1940 
1941         if (f->f3c.cc2 == 0) {
1942                 regs = fcc_names;
1943         } else {
1944                 regs = icc_names;
1945                 if (regs[f->f3c.cc] == NULL)
1946                         return (-1);
1947         }
1948 
1949         prt_name(dhp, inp->in_data.in_def.in_name, 1);
1950 
1951         bprintf(dhp, "%s, ", regs[f->f3c.cc]);
1952 
1953         if (f->f3c.i == 1)
1954                 prt_imm(dhp, sign_extend(f->f3c.simm11, 11), IMM_SIGNED);
1955         else
1956                 (void) strlcat(dhp->dh_buf, reg_names[f->f3.rs2],
1957                     dhp->dh_buflen);
1958 
1959         bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1960 
1961         return (0);
1962 }
1963 
1964 /* ARGSUSED3 */
1965 int
1966 fmt_movr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1967 {

1968         ifmt_t *f = (ifmt_t *)&instr;
1969 
1970         prt_name(dhp, inp->in_data.in_def.in_name, 1);
1971 
1972         bprintf(dhp, "%s, ", reg_names[f->f3d.rs1]);
1973 
1974         if (f->f3d.i == 1)
1975                 prt_imm(dhp, sign_extend(f->f3d.simm10, 10), IMM_SIGNED);
1976         else
1977                 (void) strlcat(dhp->dh_buf, reg_names[f->f3.rs2],
1978                     dhp->dh_buflen);
1979 
1980         bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1981 
1982         return (0);
1983 }
1984 
1985 /* ARGSUSED3 */
1986 int
1987 fmt_fpop1(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1988 {

1989         ifmt_t *f = (ifmt_t *)&instr;
1990         int flags = inp->in_data.in_def.in_flags;
1991 
1992         flags |= FLG_NOIMM;
1993 
1994         if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
1995                 prt_field("op", f->f3.op, 2);
1996                 prt_field("op3", f->f3.op3, 6);
1997                 prt_field("opf", f->fcmp.opf, 9);
1998                 prt_field("rs1", f->f3.rs1, 5);
1999                 prt_field("rs2", f->f3.rs2, 5);
2000                 prt_field("rd", f->f3.rd, 5);
2001         }
2002 
2003         prt_name(dhp, inp->in_data.in_def.in_name, 1);
2004         prt_aluargs(dhp, instr, flags);
2005 
2006         return (0);
2007 }
2008 
2009 int
2010 fmt_fpop2(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2011 {
2012         static const char *condstr_icc[16] = {
2013                 "n", "e",  "le", "l",  "leu", "lu",  "neg", "vs",
2014                 "a", "nz", "g",  "ge", "gu",  "geu", "pos", "vc"
2015         };
2016 
2017         static const char *condstr_fcc[16] = {
2018                 "n", "nz", "lg", "ul", "l",   "ug", "g",   "u",
2019                 "a", "e",  "ue", "ge", "uge", "le", "ule", "o"
2020         };
2021 

2022         ifmt_t *f = (ifmt_t *)&instr;
2023         const char *ccstr = "";
2024         char name[15];
2025 
2026         int flags = inp->in_data.in_def.in_flags;
2027         int is_cmp = (idx == 0x51 || idx == 0x52 || idx == 0x53 ||
2028             idx == 0x55 || idx == 0x56 || idx == 0x57);
2029         int is_fmov = (idx & 0x3f);
2030         int is_v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
2031         int is_compat = ((dhp->dh_debug & DIS_DEBUG_COMPAT) != 0);
2032 
2033         int p_cc = 0;
2034 
2035         is_fmov = (is_fmov == 0x1 || is_fmov == 0x2 || is_fmov == 0x3);
2036 
2037         if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
2038                 prt_field("op", f->f3.op, 2);
2039                 prt_field("op3", f->f3.op3, 6);
2040                 prt_field("opf", f->fcmp.opf, 9);
2041 
2042                 switch (idx & 0x3f) {
2043                 case 0x51:
2044                 case 0x52:
2045                 case 0x53:
2046                 case 0x55:
2047                 case 0x56:
2048                 case 0x57:
2049                         prt_field("cc", f->fcmp.cc, 2);
2050                         prt_field("rs1", f->f3.rs1, 5);
2051                         prt_field("rs2", f->f3.rs2, 5);
2052                         break;
2053 
2054                 case 0x01:
2055                 case 0x02:
2056                 case 0x03:
2057                         prt_field("opf_low", f->fmv.opf, 6);


2087                     : icc_names[f->fmv.cc & 0x3];
2088 
2089         if (ccstr == NULL)
2090                 return (-1);
2091 
2092         p_cc = (is_compat == 0 || is_v9 != 0 ||
2093             (is_cmp != 0 && f->fcmp.cc != 0) ||
2094             (is_fmov != 0 && f->fmv.cc != 0));
2095 
2096         if (p_cc != 0)
2097                 bprintf(dhp, "%s, ", ccstr);
2098 
2099         prt_aluargs(dhp, instr, flags);
2100 
2101         return (0);
2102 }
2103 
2104 int
2105 fmt_vis(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2106 {

2107         ifmt_t *f = (ifmt_t *)&instr;
2108         int flags = inp->in_data.in_def.in_flags;
2109 
2110         if ((dhp->dh_debug & DIS_DEBUG_PRTFMT) != 0) {
2111                 prt_field("op", f->f3.op, 2);
2112                 prt_field("op3", f->f3.op3, 6);
2113                 prt_field("opf", f->fcmp.opf, 9);
2114 
2115                 if (idx == 0x081) {
2116                         prt_field("mode", instr & 02L, 2);
2117                 } else {
2118                         prt_field("rs1", f->f3.rs1, 5);
2119                         prt_field("rs2", f->f3.rs2, 5);
2120                         prt_field("rd", f->f3.rd, 5);
2121                 }
2122         }
2123 
2124         prt_name(dhp, inp->in_data.in_def.in_name, 1);
2125 
2126         if (idx == 0x081) {
2127                 /* siam */
2128                 bprintf(dhp, "%d", instr & 0x7L);
2129                 return (0);
2130         }


2234         default:
2235                 fmtstr = (octal != 0) ? "0%lo" : "0x%lx";
2236         }
2237 
2238         bprintf(dhp, fmtstr, sv);
2239 }
2240 
2241 /*
2242  * return the symbolic name of a register
2243  * regset is one of the REG_* values indicating which type of register it is
2244  * such as integer, floating point, etc.
2245  * idx is the numeric value of the register
2246  *
2247  * If regset is REG_NONE, an empty, but non-NULL string is returned
2248  * NULL may be returned if the index indicates an invalid register value
2249  * such as with the %icc/%xcc sets
2250  */
2251 static const char *
2252 get_regname(dis_handle_t *dhp, int regset, uint32_t idx)
2253 {

2254         const char *regname = NULL;
2255 
2256         switch (regset) {
2257         case REG_INT:
2258                 regname = reg_names[idx];
2259                 break;
2260 
2261         case REG_FP:
2262                 regname = freg_names[idx];
2263                 break;
2264 
2265         case REG_FPD:
2266                 if (((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0) ||
2267                     ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
2268                         regname = fdreg_names[idx];
2269                 else
2270                         regname = compat_fdreg_names[idx];
2271 
2272                 break;
2273 
2274         case REG_FPQ:
2275                 if ((dhp->dh_debug & DIS_DEBUG_COMPAT) == 0)
2276                         regname = fqreg_names[idx];
2277                 else
2278                         regname = freg_names[idx];
2279 
2280                 break;
2281 
2282         case REG_CP:
2283                 regname = cpreg_names[idx];
2284                 break;
2285 
2286         case REG_ICC:
2287                 regname = icc_names[idx];
2288                 break;
2289 
2290         case REG_FCC:
2291                 regname = fcc_names[idx];
2292                 break;
2293 
2294         case REG_FSR:
2295                 regname = "%fsr";


2333 /*
2334  * put an address expression into the output buffer
2335  *
2336  * instr is the instruction to use
2337  * if nobrackets != 0, [] are not added around the instruction
2338  *
2339  * Currently this option is set when printing out the address portion
2340  * of a jmpl instruction, but otherwise 0 for load/stores
2341  *
2342  * If no debug flags are set, the full expression is output, even when
2343  * %g0 or 0x0 appears in the address
2344  *
2345  * If DIS_DEBUG_SYN_ALL or DIS_DEBUG_COMPAT are set, when %g0 or 0x0
2346  * appear in the address, they are not output.  If the wierd (and probably
2347  * shouldn't happen) address of [%g0 + %g0] or [%g0 + 0x0] is encountered,
2348  * [%g0] is output
2349  */
2350 static void
2351 prt_address(dis_handle_t *dhp, uint32_t instr, int nobrackets)
2352 {

2353         ifmt_t *f = (ifmt_t *)&instr;
2354         int32_t simm13;
2355         int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
2356         int p1 = ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0);
2357         int p2 = ((dhp->dh_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0);
2358 
2359         if (f->f3a.i == 0) {
2360                 p1 |= ((f->f3a.rs1 != 0) || f->f3.rs2 == 0);
2361                 p2 |= (f->f3.rs2 != 0);
2362 
2363                 bprintf(dhp, "%s%s%s%s%s",
2364                     (nobrackets == 0) ? "[" : "",
2365                     (p1 != 0) ? reg_names[f->f3a.rs1] : "",
2366                     (p1 != 0 && p2 != 0) ? " + " : "",
2367                     (p2 != 0) ? reg_names[f->f3.rs2] : "",
2368                     (nobrackets == 0) ? "]" : "");
2369         } else {
2370                 const char *sign;
2371 
2372                 simm13 = sign_extend(f->f3a.simm13, 13);
2373                 sign = (simm13 < 0) ? "-" : "+";
2374 
2375                 p1 |= (f->f3a.rs1 != 0);
2376                 p2 |= (p1 == 0 || simm13 != 0);
2377 


2404  * print out the arguments to an alu operation (add, sub, etc.)
2405  * conatined in 'instr'
2406  *
2407  * alu instructions have the following format:
2408  *       %rs1, %rs2, %rd    (i == 0)
2409  *       %rs1, 0xnnn, %rd   (i == 1)
2410  *         ^    ^       ^
2411  *         |    |       |
2412  *        p1    p2      p3
2413  *
2414  * flags indicates the register set to use for each position (p1, p2, p3)
2415  * as well as if immediate values (i == 1) are allowed
2416  *
2417  * if flags indicates a specific position has REG_NONE set as it's register
2418  * set, it is omitted from the output.  This is primarly used for certain
2419  * floating point operations
2420  */
2421 static void
2422 prt_aluargs(dis_handle_t *dhp, uint32_t instr, uint32_t flags)
2423 {

2424         ifmt_t *f = (ifmt_t *)&instr;
2425         const char *r1, *r2, *r3;
2426         int p1, p2, p3;
2427         unsigned int opf = 0;
2428 
2429         r1 = get_regname(dhp, FLG_P1_VAL(flags), f->f3.rs1);
2430         r2 = get_regname(dhp, FLG_P2_VAL(flags), f->f3.rs2);
2431         r3 = get_regname(dhp, FLG_P3_VAL(flags), f->f3.rd);
2432 
2433         p1 = (FLG_P1_VAL(flags) != REG_NONE);
2434         p2 = (((flags & FLG_NOIMM) == 0) || (FLG_P2_VAL(flags) != REG_NONE));
2435         p3 = (FLG_RD_VAL(flags) != REG_NONE);
2436 
2437         if (r1 == NULL || r1[0] == '\0')
2438                 p1 = 0;
2439 
2440         if (f->f3a.i == 0 && (r2 == NULL || r2[0] == '\0'))
2441                 p2 = 0;
2442 
2443         if (r3 == NULL || r3[0] == '\0')
2444                 p3 = 0;
2445 
2446         if ((f->fcmp.op == 2) && (f->fcmp.op3 == 0x36) && (f->fcmp.cc != 0))
2447                 opf = f->fcmp.opf;
2448 
2449         if ((opf == 0x151) || (opf == 0x152)) {
2450                 (void) strlcat(dhp->dh_buf, r3, dhp->dh_buflen);
2451                 (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
2452                 p3 = 0;
2453         }
2454 
2455         if (p1 != 0) {
2456                 (void) strlcat(dhp->dh_buf, r1, dhp->dh_buflen);
2457                 if (p2 != 0 || p3 != 0)
2458                         (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
2459         }
2460 
2461         if (p2 != 0) {
2462                 if (f->f3.i == 0 || ((flags & FLG_NOIMM) != 0))
2463                         (void) strlcat(dhp->dh_buf, r2, dhp->dh_buflen);
2464                 else
2465                         prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
2466                             IMM_SIGNED);
2467 
2468                 if (p3 != 0)
2469                         (void) strlcat(dhp->dh_buf, ", ", dhp->dh_buflen);
2470         }
2471 
2472         if (p3 != 0)
2473                 (void) strlcat(dhp->dh_buf, r3, dhp->dh_buflen);
2474 }
2475 
2476 static const char *
2477 get_asi_name(uint8_t asi)
2478 {
2479         switch (asi) {
2480                 case 0x04:
2481                         return ("ASI_N");
2482 
2483                 case 0x0c:
2484                         return ("ASI_NL");
2485 
2486                 case 0x10:
2487                         return ("ASI_AIUP");
2488 
2489                 case 0x11:
2490                         return ("ASI_AIUS");
2491 
2492                 case 0x14:
2493                         return ("ASI_REAL");


2725 
2726                 case 0xf9:
2727                         return ("ASI_BLK_SL");
2728 
2729                 default:
2730                         return (NULL);
2731         }
2732 }
2733 
2734 /*
2735  * just a handy function that takes care of managing the buffer length
2736  * w/ printf
2737  */
2738 
2739 /*
2740  * PRINTF LIKE 1
2741  */
2742 static void
2743 bprintf(dis_handle_t *dhp, const char *fmt, ...)
2744 {

2745         size_t curlen;
2746         va_list ap;
2747 
2748         curlen = strlen(dhp->dh_buf);
2749 
2750         va_start(ap, fmt);
2751         (void) vsnprintf(dhp->dh_buf + curlen, dhp->dh_buflen - curlen, fmt,
2752             ap);
2753         va_end(ap);
2754 }


  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.


 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


 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 


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)


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;


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 }


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:


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 {


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);


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         }


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";


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 


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");


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 }