Print this page
style fixes
comments; lint
take to dis and libdisasm with an axe; does not yet compile


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


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


 682         int i;
 683 
 684         for (i = bitlen - 1; i >= 0; --i) {
 685                 (void) fprintf(stderr, ((val & (1L << i)) != 0) ? "1" : "0");
 686 
 687                 if (i % 4 == 0 && i != 0)
 688                         (void) fprintf(stderr, " ");
 689         }
 690 }
 691 #endif /* DIS_STANDALONE */
 692 
 693 
 694 /*
 695  * print out a call instruction
 696  * format: call address  <name>
 697  */
 698 /* ARGSUSED1 */
 699 int
 700 fmt_call(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
 701 {
 702         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
 703         ifmt_t *f = (ifmt_t *)&instr;
 704 
 705         int32_t disp;
 706         size_t curlen;
 707 
 708         int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
 709 
 710         if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
 711                 prt_field("op", f->f1.op, 2);
 712                 prt_field("disp30", f->f1.disp30, 30);
 713         }
 714 
 715         disp = sign_extend(f->f1.disp30, 30) * 4;
 716 
 717         prt_name(dhp, inp->in_data.in_def.in_name, 1);
 718 
 719         bprintf(dhp, (octal != 0) ? "%s0%-11lo" : "%s0x%-10lx",
 720             (disp < 0) ? "-" : "+",
 721             (disp < 0) ? (-disp) : disp);
 722 
 723         (void) strlcat(dhx->dhx_buf, " <", dhx->dhx_buflen);
 724 
 725         curlen = strlen(dhx->dhx_buf);
 726         dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
 727             dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen - 1, NULL,
 728             NULL);
 729         (void) strlcat(dhx->dhx_buf, ">", dhx->dhx_buflen);
 730 
 731 
 732         return (0);
 733 }
 734 
 735 int
 736 fmt_sethi(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
 737 {
 738         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
 739         ifmt_t *f = (ifmt_t *)&instr;
 740 
 741         if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
 742                 prt_field("op", f->f2.op, 2);
 743                 prt_field("op2", f->f2.op2, 3);
 744                 prt_field("rd", f->f2.rd, 5);
 745                 prt_field("imm22", f->f2.imm22, 22);
 746         }
 747 
 748         if (idx == 0) {
 749                 /* unimp / illtrap */
 750                 prt_name(dhp, inp->in_data.in_def.in_name, 1);
 751                 prt_imm(dhp, f->f2.imm22, 0);
 752                 return (0);
 753         }
 754 
 755         if (f->f2.imm22 == 0 && f->f2.rd == 0) {
 756                 prt_name(dhp, "nop", 0);
 757                 return (0);
 758         }
 759 
 760         /* ?? Should we return -1 if rd == 0 && disp != 0 */
 761 
 762         prt_name(dhp, inp->in_data.in_def.in_name, 1);
 763 
 764         bprintf(dhp,
 765             ((dhp->dh_flags & DIS_OCTAL) != 0) ?
 766             "%%hi(0%lo), %s" : "%%hi(0x%lx), %s",
 767             f->f2.imm22 << 10,
 768             reg_names[f->f2.rd]);
 769 
 770         return (0);
 771 }
 772 
 773 /* ARGSUSED3 */
 774 int
 775 fmt_branch(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
 776 {
 777         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
 778         const char *name = inp->in_data.in_def.in_name;
 779         const char *r = NULL;
 780         const char *annul = "";
 781         const char *pred  = "";
 782 
 783         char buf[15];
 784 
 785         ifmt_t *f = (ifmt_t *)&instr;
 786 
 787         size_t curlen;
 788         int32_t disp;
 789         uint32_t flags = inp->in_data.in_def.in_flags;
 790         int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
 791 
 792         if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
 793                 prt_field("op", f->f2.op, 2);
 794                 prt_field("op2", f->f2.op2, 3);
 795 
 796                 switch (FLG_DISP_VAL(flags)) {
 797                 case DISP22:
 798                         prt_field("cond", f->f2a.cond, 4);
 799                         prt_field("a", f->f2a.a, 1);
 800                         prt_field("disp22", f->f2a.disp22, 22);
 801                         break;
 802 
 803                 case DISP19:
 804                         prt_field("cond", f->f2a.cond, 4);
 805                         prt_field("a", f->f2a.a, 1);
 806                         prt_field("p", f->f2b.p, 1);
 807                         prt_field("cc", f->f2b.cc, 2);
 808                         prt_field("disp19", f->f2b.disp19, 19);
 809                         break;
 810 
 811                 case DISP16:
 812                         prt_field("bit 28", ((instr & (1L << 28)) >> 28), 1);
 813                         prt_field("rcond", f->f2c.cond, 3);
 814                         prt_field("p", f->f2c.p, 1);
 815                         prt_field("rs1", f->f2c.rs1, 5);
 816                         prt_field("d16hi", f->f2c.d16hi, 2);
 817                         prt_field("d16lo", f->f2c.d16lo, 14);
 818                         break;
 819                 }
 820         }
 821 
 822         if (f->f2b.op2 == 0x01 && idx == 0x00 && f->f2b.p == 1 &&
 823             f->f2b.cc == 0x02 && ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) != 0)) {
 824                 name = "iprefetch";
 825                 flags = FLG_RS1(REG_NONE)|FLG_DISP(DISP19);
 826         }
 827 
 828 
 829         switch (FLG_DISP_VAL(flags)) {
 830         case DISP22:
 831                 disp = sign_extend(f->f2a.disp22, 22);
 832                 break;
 833 
 834         case DISP19:
 835                 disp = sign_extend(f->f2b.disp19, 19);
 836                 break;
 837 
 838         case DISP16:
 839                 disp = sign_extend((f->f2c.d16hi << 14)|f->f2c.d16lo, 16);
 840                 break;
 841 
 842         }
 843 
 844         disp *= 4;
 845 
 846         if ((FLG_RS1_VAL(flags) == REG_ICC) || (FLG_RS1_VAL(flags) == REG_FCC))
 847                 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2b.cc);
 848         else
 849                 r = get_regname(dhp, FLG_RS1_VAL(flags), f->f2c.rs1);
 850 
 851         if (r == NULL)
 852                 return (-1);
 853 
 854         if (f->f2a.a == 1)
 855                 annul = ",a";
 856 
 857         if ((flags & FLG_PRED) != 0) {
 858                 if (f->f2b.p == 0) {
 859                         pred = ",pn";
 860                 } else {
 861                         if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0)
 862                                 pred = ",pt";
 863                 }
 864         }
 865 
 866         (void) snprintf(buf, sizeof (buf), "%s%s%s", name, annul, pred);
 867         prt_name(dhp, buf, 1);
 868 
 869 
 870         switch (FLG_DISP_VAL(flags)) {
 871         case DISP22:
 872                 bprintf(dhp,
 873                     (octal != 0) ? "%s0%-11lo <" : "%s0x%-10lx <",
 874                     (disp < 0) ? "-" : "+",
 875                     (disp < 0) ? (-disp) : disp);
 876                 break;
 877 
 878         case DISP19:
 879                 bprintf(dhp,
 880                     (octal != 0) ? "%s, %s0%-5lo <" :
 881                     "%s, %s0x%-04lx <", r,
 882                     (disp < 0) ? "-" : "+",
 883                     (disp < 0) ? (-disp) : disp);
 884                 break;
 885 
 886         case DISP16:
 887                 bprintf(dhp,
 888                     (octal != 0) ? "%s, %s0%-6lo <" : "%s, %s0x%-5lx <",
 889                     r,
 890                     (disp < 0) ? "-" : "+",
 891                     (disp < 0) ? (-disp) : disp);
 892                 break;
 893         }
 894 
 895         curlen = strlen(dhx->dhx_buf);
 896         dhp->dh_lookup(dhp->dh_data, dhp->dh_addr + (int64_t)disp,
 897             dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen - 1, NULL, NULL);
 898 
 899         (void) strlcat(dhx->dhx_buf, ">", dhx->dhx_buflen);
 900 
 901         return (0);
 902 }
 903 
 904 
 905 
 906 /*
 907  * print out the compare and swap instructions (casa/casxa)
 908  * format: casa/casxa [%rs1] imm_asi, %rs2, %rd
 909  *          casa/casxa [%rs1] %asi, %rs2, %rd
 910  *
 911  * If DIS_DEBUG_SYN_ALL is set, synthetic instructions are emitted
 912  * when an immediate ASI value is given as follows:
 913  *
 914  * casa  [%rs1]#ASI_P, %rs2, %rd    -> cas   [%rs1], %rs2, %rd
 915  * casa  [%rs1]#ASI_P_L, %rs2, %rd  -> casl  [%rs1], %rs2, %rd
 916  * casxa [%rs1]#ASI_P, %rs2, %rd    -> casx  [%rs1], %rs2, %rd
 917  * casxa [%rs1]#ASI_P_L, %rs2, %rd  -> casxl [%rs1], %rs2, %rd
 918  */
 919 static int
 920 fmt_cas(dis_handle_t *dhp, uint32_t instr, const char *name)
 921 {
 922         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
 923         ifmt_t *f = (ifmt_t *)&instr;
 924         const char *asistr = NULL;
 925         int noasi = 0;
 926 
 927         asistr = get_asi_name(f->f3.asi);
 928 
 929         if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT)) != 0) {
 930                 if (f->f3.op3 == 0x3c && f->f3.i == 0) {
 931                         if (f->f3.asi == 0x80) {
 932                                 noasi = 1;
 933                                 name = "cas";
 934                         }
 935 
 936                         if (f->f3.asi == 0x88) {
 937                                 noasi = 1;
 938                                 name = "casl";
 939                         }
 940                 }
 941 
 942                 if (f->f3.op3 == 0x3e && f->f3.i == 0) {
 943                         if (f->f3.asi == 0x80) {
 944                                 noasi = 1;
 945                                 name = "casx";
 946                         }
 947 
 948                         if (f->f3.asi == 0x88) {
 949                                 noasi = 1;
 950                                 name = "casxl";
 951                         }
 952                 }
 953         }
 954 
 955         prt_name(dhp, name, 1);
 956 
 957         bprintf(dhp, "[%s]", reg_names[f->f3.rs1]);
 958 
 959         if (noasi == 0) {
 960                 (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
 961                 prt_asi(dhp, instr);
 962         }
 963 
 964         bprintf(dhp, ", %s, %s", reg_names[f->f3.rs2], reg_names[f->f3.rd]);
 965 
 966         if (noasi == 0 && asistr != NULL)
 967                 bprintf(dhp, "\t<%s>", asistr);
 968 
 969         return (0);
 970 }
 971 
 972 /*
 973  * format a load/store instruction
 974  * format: ldXX [%rs1 + %rs2], %rd        load, i==0
 975  *          ldXX [%rs1 +/- nn], %rd       load, i==1
 976  *          ldXX [%rs1 + %rs2] #XX, %rd   load w/ imm_asi, i==0
 977  *          ldXX [%rs1 +/- nn] %asi, %rd  load from asi[%asi], i==1
 978  *
 979  *          stXX %rd, [%rs1 + %rs2]       store, i==0
 980  *          stXX %rd, [%rs1 +/- nn]       store, i==1


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


1201                                 if (asistr != NULL)
1202                                         bprintf(dhp, "\t<%s>", asistr);
1203 
1204                                 return (0);
1205 
1206                         default:
1207                                 break;
1208                 }
1209 
1210         }
1211 
1212         regstr = get_regname(dhp, FLG_RD_VAL(flags), f->f3.rd);
1213 
1214         if (f->f3.i == 0)
1215                 asistr = get_asi_name(f->f3.asi);
1216 
1217         prt_name(dhp, iname, 1);
1218 
1219         if ((flags & FLG_STORE) != 0) {
1220                 if (regstr[0] != '\0') {
1221                         (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1222                         (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1223                 }
1224 
1225                 prt_address(dhp, instr, 0);
1226                 if ((flags & FLG_ASI) != 0) {
1227                         (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1228                         prt_asi(dhp, instr);
1229                 }
1230         } else {
1231                 prt_address(dhp, instr, 0);
1232                 if ((flags & FLG_ASI) != 0) {
1233                         (void) strlcat(dhx->dhx_buf, " ", dhx->dhx_buflen);
1234                         prt_asi(dhp, instr);
1235                 }
1236 
1237                 if (regstr[0] != '\0') {
1238                         (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1239                         (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1240                 }
1241         }
1242 
1243         if ((flags & FLG_ASI) != 0 && asistr != NULL)
1244                 bprintf(dhp, "\t<%s>", asistr);
1245 
1246         return (0);
1247 }
1248 
1249 static int
1250 fmt_cpop(dis_handle_t *dhp, uint32_t instr, const inst_t *inp)
1251 {
1252         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1253         ifmt_t *f = (ifmt_t *)&instr;
1254         int flags = FLG_P1(REG_CP)|FLG_P2(REG_CP)|FLG_NOIMM|FLG_P3(REG_CP);
1255 
1256         if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1257                 prt_field("op", f->fcp.op, 2);
1258                 prt_field("op3", f->fcp.op3, 6);
1259                 prt_field("opc", f->fcp.opc, 9);
1260                 prt_field("rs1", f->fcp.rs1, 5);
1261                 prt_field("rs2", f->fcp.rs2, 5);
1262                 prt_field("rd", f->fcp.rd, 5);
1263         }
1264 
1265         prt_name(dhp, inp->in_data.in_def.in_name, 1);
1266         prt_imm(dhp, f->fcp.opc, 0);
1267 
1268         (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1269         (void) prt_aluargs(dhp, instr, flags);
1270 
1271         return (0);
1272 }
1273 
1274 static int
1275 dis_fmt_rdwr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1276 {
1277         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1278         const char *psr_str = "%psr";
1279         const char *wim_str = "%wim";
1280         const char *tbr_str = "%tbr";
1281 
1282         const char *name = inp->in_data.in_def.in_name;
1283         const char *regstr = NULL;
1284 
1285         ifmt_t *f = (ifmt_t *)&instr;
1286 
1287         int rd = (idx < 0x30);
1288         int v9 = (dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI));
1289         int ridx = f->f3.rs1;
1290         int i, first;
1291         int pr_rs1 = 1;
1292         int pr_rs2 = 1;
1293 
1294         int use_mask = 1;
1295         uint32_t mask;
1296 
1297         if (rd == 0)


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


1455 
1456         if (regstr == NULL)
1457                 return (-1);
1458 
1459         if (use_mask != 0 && ((1L << ridx) & mask) == 0)
1460                 return (-1);
1461 
1462         prt_name(dhp, name, 1);
1463 
1464         if (rd != 0) {
1465                 bprintf(dhp, "%s, %s", regstr, reg_names[f->f3.rd]);
1466         } else {
1467                 if (pr_rs1 == 1)
1468                         bprintf(dhp, "%s, ", reg_names[f->f3.rs1]);
1469 
1470                 if (pr_rs2 != 0) {
1471                         if (f->f3.i == 1)
1472                                 prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
1473                                     IMM_SIGNED);
1474                         else
1475                                 (void) strlcat(dhx->dhx_buf,
1476                                     reg_names[f->f3.rs2], dhx->dhx_buflen);
1477                         (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
1478                 }
1479 
1480                 (void) strlcat(dhx->dhx_buf, regstr, dhx->dhx_buflen);
1481         }
1482 
1483         return (0);
1484 }
1485 
1486 /* ARGSUSED3 */
1487 int
1488 fmt_trap(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1489 {
1490         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1491         ifmt_t *f = (ifmt_t *)&instr;
1492 
1493         int v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
1494         int p_rs1, p_t;
1495 
1496         if (f->ftcc.undef != 0)
1497                 return (-1);
1498 
1499         if (icc_names[f->ftcc.cc] == NULL)
1500                 return (-1);
1501 
1502         if (f->ftcc.i == 1 && f->ftcc.undef2 != 0)
1503                 return (-1);
1504 
1505         if (f->ftcc2.i == 0 && f->ftcc2.undef2 != 0)
1506                 return (-1);
1507 
1508         p_rs1 = ((f->ftcc.rs1 != 0) ||
1509             ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0));
1510 
1511         if (f->ftcc.i == 0) {
1512                 p_t = (f->f3.rs2 != 0 || p_rs1 == 0);
1513 
1514                 bprintf(dhp, "%-9s %s%s%s%s%s", inp->in_data.in_def.in_name,
1515                     (v9 != 0) ? icc_names[f->ftcc2.cc] : "",
1516                     (v9 != 0) ? ", " : "",
1517                     (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "",
1518                     (p_rs1 != 0) ? " + " : "",
1519                     (p_t != 0) ? reg_names[f->f3.rs2] : "");
1520         } else {
1521                 bprintf(dhp, "%-9s %s%s%s%s0x%x", inp->in_data.in_def.in_name,
1522                     (v9 != 0) ? icc_names[f->ftcc2.cc] : "",
1523                     (v9 != 0) ? ", " : "",
1524                     (p_rs1 != 0) ? reg_names[f->ftcc2.rs1] : "",
1525                     (p_rs1 != 0) ? " + " : "",
1526                     f->ftcc.immtrap);
1527         }
1528         return (0);
1529 }


1547                 cnt = f->f3b.shcnt;
1548                 (void) strlcat(name, "x", sizeof (name));
1549         }
1550 
1551         prt_name(dhp, name, 1);
1552 
1553         if (f->f3b.i == 1)
1554                 bprintf(dhp, (octal != 0) ? "%s, 0%lo, %s" : "%s, 0x%lx, %s",
1555                     reg_names[f->f3.rs1], cnt, reg_names[f->f3.rd]);
1556         else
1557                 bprintf(dhp, "%s, %s, %s", reg_names[f->f3.rs1],
1558                     reg_names[f->f3.rs2], reg_names[f->f3.rd]);
1559 
1560         return (0);
1561 }
1562 
1563 /* ARGSUSED3 */
1564 static int
1565 prt_jmpl(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1566 {
1567         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1568         const char *name = inp->in_data.in_def.in_name;
1569         ifmt_t *f = (ifmt_t *)&instr;
1570 
1571         if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0))
1572                 name = "call";
1573 
1574         if (f->f3.rd == 0) {
1575                 if (f->f3.i == 1 && f->f3a.simm13 == 8) {
1576                         if (f->f3.rs1 == 15) {
1577                                 prt_name(dhp, "retl", 0);
1578                                 return (0);
1579                         }
1580 
1581                         if (f->f3.rs1 == 31) {
1582                                 prt_name(dhp, "ret", 0);
1583                                 return (0);
1584                         }
1585                 }
1586 
1587                 name = "jmp";
1588         }
1589 
1590         prt_name(dhp, name, 1);
1591         prt_address(dhp, instr, 1);
1592 
1593         if (f->f3.rd == 0)
1594                 return (0);
1595 
1596         if (f->f3.rd == 15 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0))
1597                 return (0);
1598 
1599         bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1600 
1601         return (0);
1602 }
1603 
1604 int
1605 fmt_alu(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1606 {
1607         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1608         ifmt_t *f = (ifmt_t *)&instr;
1609 
1610         const char *name = inp->in_data.in_def.in_name;
1611         int flags = inp->in_data.in_def.in_flags;
1612         int arg = 0;
1613 
1614         if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1615                 prt_field("op", f->f3.op, 2);
1616                 prt_field("op3", f->f3.op3, 6);
1617                 prt_field("rs1", f->f3.rs1, 5);
1618 
1619                 switch (idx) {
1620                         /* TODO: more formats */
1621 
1622                 default:
1623                         if (f->f3.i == 0)
1624                                 prt_field("rs2", f->f3.rs2, 5);
1625                         else
1626                                 prt_field("simm13", f->f3a.simm13, 13);
1627 
1628                         prt_field("rd", f->f3.rd, 5);
1629                 }
1630 
1631         }
1632 
1633         switch (idx) {
1634         case 0x00:
1635                 /* add */
1636 
1637                 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1638                         break;
1639 
1640                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1641                     f->f3a.simm13 == 1) {
1642                         name = "inc";
1643                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1644                         break;
1645                 }
1646 
1647                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1648                     f->f3a.simm13 != 1) {
1649                         name = "inc";
1650                         flags = FLG_P1(REG_NONE);
1651                         break;
1652                 }
1653                 break;
1654 
1655         case 0x02:
1656                 /* or */
1657 
1658                 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1659                     == 0)
1660                         break;
1661 
1662                 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) != 0) {
1663                         if (f->f3.rs1 == f->f3.rd) {
1664                                 name = "bset";
1665                                 flags = FLG_P1(REG_NONE);
1666                                 break;
1667                         }
1668                 }
1669 
1670                 if (((f->f3.i == 0 && f->f3.rs2 == 0) ||
1671                     (f->f3.i == 1 && f->f3a.simm13 == 0)) &&
1672                     (f->f3.rs1 == 0)) {
1673                         name = "clr";
1674                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1675                         break;
1676                 }
1677 
1678                 if (f->f3.rs1 == 0) {
1679                         name = "mov";
1680                         flags = FLG_P1(REG_NONE);
1681                         break;
1682                 }
1683                 break;
1684 
1685         case 0x04:
1686                 /* sub */
1687 
1688                 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1689                     == 0)
1690                         break;
1691 
1692                 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 == f->f3.rd) {
1693                         name = "neg";
1694                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE);
1695                         break;
1696                 }
1697 
1698                 if (f->f3.rs1 == 0 && f->f3.i == 0 && f->f3.rs2 != f->f3.rd) {
1699                         name = "neg";
1700                         flags = FLG_P1(REG_NONE);
1701                         break;
1702                 }
1703 
1704                 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1705                         break;
1706 
1707                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1708                     f->f3a.simm13 == 1) {
1709                         name = "dec";
1710                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1711                         break;
1712                 }
1713 
1714                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1715                     f->f3a.simm13 != 1) {
1716                         name = "dec";
1717                         flags = FLG_P1(REG_NONE);
1718                         break;
1719                 }
1720                 break;
1721 
1722         case 0x07:
1723                 /* xnor */
1724 
1725                 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1726                     == 0)
1727                         break;
1728 
1729                 /*
1730                  * xnor -> not when you have:
1731                  *       xnor %rs1, 0x0 or %g0, %rd
1732                  */
1733                 if ((f->f3.i == 0 && f->f3.rs2 != 0) ||
1734                     (f->f3.i == 1 && f->f3a.simm13 != 0))
1735                         break;
1736 
1737                 name = "not";
1738 
1739                 if (f->f3.rs1 == f->f3.rd)
1740                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM|
1741                             FLG_P3(REG_INT);
1742                 else
1743                         flags = FLG_P1(REG_INT)|FLG_P2(REG_NONE)|FLG_NOIMM|
1744                             FLG_P3(REG_INT);
1745 
1746                 break;
1747 
1748         case 0x10:
1749                 /* addcc */
1750 
1751                 if ((dhx->dhx_debug & DIS_DEBUG_SYN_ALL) == 0)
1752                         break;
1753 
1754                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1755                     f->f3a.simm13 == 1) {
1756                         name = "inccc";
1757                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1758                         break;
1759                 }
1760 
1761                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1762                     f->f3a.simm13 != 1) {
1763                         name = "inccc";
1764                         flags = FLG_P1(REG_NONE);
1765                         break;
1766                 }
1767                 break;
1768 
1769         case 0x11:
1770                 /* andcc */
1771 
1772                 if (f->f3.rd != 0)
1773                         break;
1774 
1775                 if ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL))
1776                     == 0)
1777                         break;
1778 
1779                 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0) &&
1780                     ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) == 0))
1781                         break;
1782 
1783                 name = "btst";
1784                 flags = FLG_P1(REG_NONE);
1785                 f->f3.rd = f->f3.rs1;
1786                 break;
1787 
1788         case 0x12:
1789                 /* orcc */
1790 
1791                 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1792                     == 0)
1793                         break;
1794 
1795                 if (f->f3.rs1 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1796                         name = "tst";
1797                         flags = FLG_P1(REG_NONE)|FLG_P3(REG_NONE);
1798                         break;
1799                 }
1800 
1801                 if (f->f3.rs2 == 0 && f->f3.rd == 0 && f->f3.i == 0) {
1802                         name = "tst";
1803                         flags = FLG_P2(REG_NONE)|FLG_P3(REG_NONE);
1804                         break;
1805                 }
1806 
1807                 break;
1808 
1809         case 0x14:
1810                 /* subcc */
1811 
1812                 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1813                     == 0)
1814                         break;
1815 
1816                 if (f->f3.rd == 0) {
1817                         name = "cmp";
1818                         flags = FLG_P3(REG_NONE);
1819                         break;
1820                 }
1821 
1822                 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0)
1823                         break;
1824 
1825                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1826                     f->f3a.simm13 == 1) {
1827                         name = "deccc";
1828                         flags = FLG_P1(REG_NONE)|FLG_P2(REG_NONE)|FLG_NOIMM;
1829                         break;
1830                 }
1831 
1832                 if (f->f3.rs1 == f->f3.rd && f->f3.i == 1 &&
1833                     f->f3a.simm13 != 1) {
1834                         name = "deccc";
1835                         flags = FLG_P1(REG_NONE);
1836                         break;
1837                 }
1838 
1839                 break;
1840 
1841         case 0x25:
1842         case 0x26:


1862 
1863         case 0x38:
1864                 /* jmpl */
1865                 return (prt_jmpl(dhp, instr, inp, idx));
1866 
1867         case 0x39:
1868                 /* rett / return */
1869                 prt_name(dhp, name, 1);
1870                 prt_address(dhp, instr, 1);
1871                 return (0);
1872 
1873         case 0x3b:
1874                 /* flush */
1875                 prt_name(dhp, name, 1);
1876                 prt_address(dhp, instr, 0);
1877                 return (0);
1878 
1879         case 0x3c:
1880         case 0x3d:
1881                 /* save / restore */
1882                 if ((dhx->dhx_debug & (DIS_DEBUG_SYN_ALL|DIS_DEBUG_COMPAT))
1883                     == 0)
1884                         break;
1885 
1886                 if (f->f3.rs1 != 0 || f->f3.rs2 != 0 || f->f3.rd != 0)
1887                         break;
1888 
1889                 if (f->f3.i != 0 && ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0))
1890                         break;
1891 
1892                 prt_name(dhp, name, 0);
1893                 return (0);
1894         }
1895 
1896         if (FLG_P1_VAL(flags) != REG_NONE || FLG_P2_VAL(flags) != REG_NONE ||
1897             FLG_P3_VAL(flags) != REG_NONE)
1898                 arg = 1;
1899 
1900         prt_name(dhp, name, (arg != 0));
1901         prt_aluargs(dhp, instr, flags);
1902 
1903         return (0);
1904 }
1905 
1906 /* ARGSUSED1 */
1907 int
1908 fmt_regwin(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1909 {


1913 
1914 /* ARGSUSED1 */
1915 int
1916 fmt_trap_ret(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1917 {
1918         ifmt_t *f = (ifmt_t *)&instr;
1919         prt_name(dhp, inp->in_data.in_def.in_name, 1);
1920 
1921         if (f->f3.rd == 0xf) {
1922                 /* jpriv */
1923                 prt_address(dhp, instr, 1);
1924         }
1925 
1926         return (0);
1927 }
1928 
1929 /* ARGSUSED3 */
1930 int
1931 fmt_movcc(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1932 {
1933         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1934         ifmt_t *f = (ifmt_t *)&instr;
1935         const char **regs = NULL;
1936 
1937         if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
1938                 prt_field("op", f->f3c.op, 2);
1939                 prt_field("op3", f->f3c.op3, 6);
1940                 prt_field("cond", f->f3c.cond, 4);
1941                 prt_field("cc2", f->f3c.cc2, 1);
1942                 prt_field("cc", f->f3c.cc, 2);
1943                 prt_field("i", f->f3c.i, 1);
1944 
1945                 if (f->f3c.i == 0)
1946                         prt_field("rs2", f->f3.rs2, 5);
1947                 else
1948                         prt_field("simm11", f->f3c.simm11, 11);
1949 
1950                 prt_field("rd", f->f3.rd, 5);
1951         }
1952 
1953         if (f->f3c.cc2 == 0) {
1954                 regs = fcc_names;
1955         } else {
1956                 regs = icc_names;
1957                 if (regs[f->f3c.cc] == NULL)
1958                         return (-1);
1959         }
1960 
1961         prt_name(dhp, inp->in_data.in_def.in_name, 1);
1962 
1963         bprintf(dhp, "%s, ", regs[f->f3c.cc]);
1964 
1965         if (f->f3c.i == 1)
1966                 prt_imm(dhp, sign_extend(f->f3c.simm11, 11), IMM_SIGNED);
1967         else
1968                 (void) strlcat(dhx->dhx_buf, reg_names[f->f3.rs2],
1969                     dhx->dhx_buflen);
1970 
1971         bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1972 
1973         return (0);
1974 }
1975 
1976 /* ARGSUSED3 */
1977 int
1978 fmt_movr(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
1979 {
1980         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
1981         ifmt_t *f = (ifmt_t *)&instr;
1982 
1983         prt_name(dhp, inp->in_data.in_def.in_name, 1);
1984 
1985         bprintf(dhp, "%s, ", reg_names[f->f3d.rs1]);
1986 
1987         if (f->f3d.i == 1)
1988                 prt_imm(dhp, sign_extend(f->f3d.simm10, 10), IMM_SIGNED);
1989         else
1990                 (void) strlcat(dhx->dhx_buf, reg_names[f->f3.rs2],
1991                     dhx->dhx_buflen);
1992 
1993         bprintf(dhp, ", %s", reg_names[f->f3.rd]);
1994 
1995         return (0);
1996 }
1997 
1998 /* ARGSUSED3 */
1999 int
2000 fmt_fpop1(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2001 {
2002         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2003         ifmt_t *f = (ifmt_t *)&instr;
2004         int flags = inp->in_data.in_def.in_flags;
2005 
2006         flags |= FLG_NOIMM;
2007 
2008         if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2009                 prt_field("op", f->f3.op, 2);
2010                 prt_field("op3", f->f3.op3, 6);
2011                 prt_field("opf", f->fcmp.opf, 9);
2012                 prt_field("rs1", f->f3.rs1, 5);
2013                 prt_field("rs2", f->f3.rs2, 5);
2014                 prt_field("rd", f->f3.rd, 5);
2015         }
2016 
2017         prt_name(dhp, inp->in_data.in_def.in_name, 1);
2018         prt_aluargs(dhp, instr, flags);
2019 
2020         return (0);
2021 }
2022 
2023 int
2024 fmt_fpop2(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2025 {
2026         static const char *condstr_icc[16] = {
2027                 "n", "e",  "le", "l",  "leu", "lu",  "neg", "vs",
2028                 "a", "nz", "g",  "ge", "gu",  "geu", "pos", "vc"
2029         };
2030 
2031         static const char *condstr_fcc[16] = {
2032                 "n", "nz", "lg", "ul", "l",   "ug", "g",   "u",
2033                 "a", "e",  "ue", "ge", "uge", "le", "ule", "o"
2034         };
2035 
2036         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2037         ifmt_t *f = (ifmt_t *)&instr;
2038         const char *ccstr = "";
2039         char name[15];
2040 
2041         int flags = inp->in_data.in_def.in_flags;
2042         int is_cmp = (idx == 0x51 || idx == 0x52 || idx == 0x53 ||
2043             idx == 0x55 || idx == 0x56 || idx == 0x57);
2044         int is_fmov = (idx & 0x3f);
2045         int is_v9 = ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0);
2046         int is_compat = ((dhx->dhx_debug & DIS_DEBUG_COMPAT) != 0);
2047 
2048         int p_cc = 0;
2049 
2050         is_fmov = (is_fmov == 0x1 || is_fmov == 0x2 || is_fmov == 0x3);
2051 
2052         if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2053                 prt_field("op", f->f3.op, 2);
2054                 prt_field("op3", f->f3.op3, 6);
2055                 prt_field("opf", f->fcmp.opf, 9);
2056 
2057                 switch (idx & 0x3f) {
2058                 case 0x51:
2059                 case 0x52:
2060                 case 0x53:
2061                 case 0x55:
2062                 case 0x56:
2063                 case 0x57:
2064                         prt_field("cc", f->fcmp.cc, 2);
2065                         prt_field("rs1", f->f3.rs1, 5);
2066                         prt_field("rs2", f->f3.rs2, 5);
2067                         break;
2068 
2069                 case 0x01:
2070                 case 0x02:
2071                 case 0x03:
2072                         prt_field("opf_low", f->fmv.opf, 6);


2102                     : icc_names[f->fmv.cc & 0x3];
2103 
2104         if (ccstr == NULL)
2105                 return (-1);
2106 
2107         p_cc = (is_compat == 0 || is_v9 != 0 ||
2108             (is_cmp != 0 && f->fcmp.cc != 0) ||
2109             (is_fmov != 0 && f->fmv.cc != 0));
2110 
2111         if (p_cc != 0)
2112                 bprintf(dhp, "%s, ", ccstr);
2113 
2114         prt_aluargs(dhp, instr, flags);
2115 
2116         return (0);
2117 }
2118 
2119 int
2120 fmt_vis(dis_handle_t *dhp, uint32_t instr, const inst_t *inp, int idx)
2121 {
2122         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2123         ifmt_t *f = (ifmt_t *)&instr;
2124         int flags = inp->in_data.in_def.in_flags;
2125 
2126         if ((dhx->dhx_debug & DIS_DEBUG_PRTFMT) != 0) {
2127                 prt_field("op", f->f3.op, 2);
2128                 prt_field("op3", f->f3.op3, 6);
2129                 prt_field("opf", f->fcmp.opf, 9);
2130 
2131                 if (idx == 0x081) {
2132                         prt_field("mode", instr & 02L, 2);
2133                 } else {
2134                         prt_field("rs1", f->f3.rs1, 5);
2135                         prt_field("rs2", f->f3.rs2, 5);
2136                         prt_field("rd", f->f3.rd, 5);
2137                 }
2138         }
2139 
2140         prt_name(dhp, inp->in_data.in_def.in_name, 1);
2141 
2142         if (idx == 0x081) {
2143                 /* siam */
2144                 bprintf(dhp, "%d", instr & 0x7L);
2145                 return (0);
2146         }


2250         default:
2251                 fmtstr = (octal != 0) ? "0%lo" : "0x%lx";
2252         }
2253 
2254         bprintf(dhp, fmtstr, sv);
2255 }
2256 
2257 /*
2258  * return the symbolic name of a register
2259  * regset is one of the REG_* values indicating which type of register it is
2260  * such as integer, floating point, etc.
2261  * idx is the numeric value of the register
2262  *
2263  * If regset is REG_NONE, an empty, but non-NULL string is returned
2264  * NULL may be returned if the index indicates an invalid register value
2265  * such as with the %icc/%xcc sets
2266  */
2267 static const char *
2268 get_regname(dis_handle_t *dhp, int regset, uint32_t idx)
2269 {
2270         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2271         const char *regname = NULL;
2272 
2273         switch (regset) {
2274         case REG_INT:
2275                 regname = reg_names[idx];
2276                 break;
2277 
2278         case REG_FP:
2279                 regname = freg_names[idx];
2280                 break;
2281 
2282         case REG_FPD:
2283                 if (((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0) ||
2284                     ((dhp->dh_flags & (DIS_SPARC_V9|DIS_SPARC_V9_SGI)) != 0))
2285                         regname = fdreg_names[idx];
2286                 else
2287                         regname = compat_fdreg_names[idx];
2288 
2289                 break;
2290 
2291         case REG_FPQ:
2292                 if ((dhx->dhx_debug & DIS_DEBUG_COMPAT) == 0)
2293                         regname = fqreg_names[idx];
2294                 else
2295                         regname = freg_names[idx];
2296 
2297                 break;
2298 
2299         case REG_CP:
2300                 regname = cpreg_names[idx];
2301                 break;
2302 
2303         case REG_ICC:
2304                 regname = icc_names[idx];
2305                 break;
2306 
2307         case REG_FCC:
2308                 regname = fcc_names[idx];
2309                 break;
2310 
2311         case REG_FSR:
2312                 regname = "%fsr";


2350 /*
2351  * put an address expression into the output buffer
2352  *
2353  * instr is the instruction to use
2354  * if nobrackets != 0, [] are not added around the instruction
2355  *
2356  * Currently this option is set when printing out the address portion
2357  * of a jmpl instruction, but otherwise 0 for load/stores
2358  *
2359  * If no debug flags are set, the full expression is output, even when
2360  * %g0 or 0x0 appears in the address
2361  *
2362  * If DIS_DEBUG_SYN_ALL or DIS_DEBUG_COMPAT are set, when %g0 or 0x0
2363  * appear in the address, they are not output.  If the wierd (and probably
2364  * shouldn't happen) address of [%g0 + %g0] or [%g0 + 0x0] is encountered,
2365  * [%g0] is output
2366  */
2367 static void
2368 prt_address(dis_handle_t *dhp, uint32_t instr, int nobrackets)
2369 {
2370         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2371         ifmt_t *f = (ifmt_t *)&instr;
2372         int32_t simm13;
2373         int octal = ((dhp->dh_flags & DIS_OCTAL) != 0);
2374         int p1 = ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0);
2375         int p2 = ((dhx->dhx_debug & (DIS_DEBUG_COMPAT|DIS_DEBUG_SYN_ALL)) == 0);
2376 
2377         if (f->f3a.i == 0) {
2378                 p1 |= ((f->f3a.rs1 != 0) || f->f3.rs2 == 0);
2379                 p2 |= (f->f3.rs2 != 0);
2380 
2381                 bprintf(dhp, "%s%s%s%s%s",
2382                     (nobrackets == 0) ? "[" : "",
2383                     (p1 != 0) ? reg_names[f->f3a.rs1] : "",
2384                     (p1 != 0 && p2 != 0) ? " + " : "",
2385                     (p2 != 0) ? reg_names[f->f3.rs2] : "",
2386                     (nobrackets == 0) ? "]" : "");
2387         } else {
2388                 const char *sign;
2389 
2390                 simm13 = sign_extend(f->f3a.simm13, 13);
2391                 sign = (simm13 < 0) ? "-" : "+";
2392 
2393                 p1 |= (f->f3a.rs1 != 0);
2394                 p2 |= (p1 == 0 || simm13 != 0);
2395 


2422  * print out the arguments to an alu operation (add, sub, etc.)
2423  * conatined in 'instr'
2424  *
2425  * alu instructions have the following format:
2426  *       %rs1, %rs2, %rd    (i == 0)
2427  *       %rs1, 0xnnn, %rd   (i == 1)
2428  *         ^    ^       ^
2429  *         |    |       |
2430  *        p1    p2      p3
2431  *
2432  * flags indicates the register set to use for each position (p1, p2, p3)
2433  * as well as if immediate values (i == 1) are allowed
2434  *
2435  * if flags indicates a specific position has REG_NONE set as it's register
2436  * set, it is omitted from the output.  This is primarly used for certain
2437  * floating point operations
2438  */
2439 static void
2440 prt_aluargs(dis_handle_t *dhp, uint32_t instr, uint32_t flags)
2441 {
2442         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2443         ifmt_t *f = (ifmt_t *)&instr;
2444         const char *r1, *r2, *r3;
2445         int p1, p2, p3;
2446         unsigned int opf = 0;
2447 
2448         r1 = get_regname(dhp, FLG_P1_VAL(flags), f->f3.rs1);
2449         r2 = get_regname(dhp, FLG_P2_VAL(flags), f->f3.rs2);
2450         r3 = get_regname(dhp, FLG_P3_VAL(flags), f->f3.rd);
2451 
2452         p1 = (FLG_P1_VAL(flags) != REG_NONE);
2453         p2 = (((flags & FLG_NOIMM) == 0) || (FLG_P2_VAL(flags) != REG_NONE));
2454         p3 = (FLG_RD_VAL(flags) != REG_NONE);
2455 
2456         if (r1 == NULL || r1[0] == '\0')
2457                 p1 = 0;
2458 
2459         if (f->f3a.i == 0 && (r2 == NULL || r2[0] == '\0'))
2460                 p2 = 0;
2461 
2462         if (r3 == NULL || r3[0] == '\0')
2463                 p3 = 0;
2464 
2465         if ((f->fcmp.op == 2) && (f->fcmp.op3 == 0x36) && (f->fcmp.cc != 0))
2466                 opf = f->fcmp.opf;
2467 
2468         if ((opf == 0x151) || (opf == 0x152)) {
2469                 (void) strlcat(dhx->dhx_buf, r3, dhx->dhx_buflen);
2470                 (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
2471                 p3 = 0;
2472         }
2473 
2474         if (p1 != 0) {
2475                 (void) strlcat(dhx->dhx_buf, r1, dhx->dhx_buflen);
2476                 if (p2 != 0 || p3 != 0)
2477                         (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
2478         }
2479 
2480         if (p2 != 0) {
2481                 if (f->f3.i == 0 || ((flags & FLG_NOIMM) != 0))
2482                         (void) strlcat(dhx->dhx_buf, r2, dhx->dhx_buflen);
2483                 else
2484                         prt_imm(dhp, sign_extend(f->f3a.simm13, 13),
2485                             IMM_SIGNED);
2486 
2487                 if (p3 != 0)
2488                         (void) strlcat(dhx->dhx_buf, ", ", dhx->dhx_buflen);
2489         }
2490 
2491         if (p3 != 0)
2492                 (void) strlcat(dhx->dhx_buf, r3, dhx->dhx_buflen);
2493 }
2494 
2495 static const char *
2496 get_asi_name(uint8_t asi)
2497 {
2498         switch (asi) {
2499                 case 0x04:
2500                         return ("ASI_N");
2501 
2502                 case 0x0c:
2503                         return ("ASI_NL");
2504 
2505                 case 0x10:
2506                         return ("ASI_AIUP");
2507 
2508                 case 0x11:
2509                         return ("ASI_AIUS");
2510 
2511                 case 0x14:
2512                         return ("ASI_REAL");


2744 
2745                 case 0xf9:
2746                         return ("ASI_BLK_SL");
2747 
2748                 default:
2749                         return (NULL);
2750         }
2751 }
2752 
2753 /*
2754  * just a handy function that takes care of managing the buffer length
2755  * w/ printf
2756  */
2757 
2758 /*
2759  * PRINTF LIKE 1
2760  */
2761 static void
2762 bprintf(dis_handle_t *dhp, const char *fmt, ...)
2763 {
2764         dis_handle_sparc_t *dhx = dhp->dh_arch_private;
2765         size_t curlen;
2766         va_list ap;
2767 
2768         curlen = strlen(dhx->dhx_buf);
2769 
2770         va_start(ap, fmt);
2771         (void) vsnprintf(dhx->dhx_buf + curlen, dhx->dhx_buflen - curlen, fmt,
2772             ap);
2773         va_end(ap);
2774 }