@@ -52,6 +52,7 @@ struct disas_alt {
5252 struct {
5353 char * str ; /* instruction string */
5454 int offset ; /* instruction offset */
55+ int nops ; /* number of nops */
5556 } insn [DISAS_ALT_INSN_MAX ]; /* alternative instructions */
5657 int insn_idx ; /* index of the next instruction to print */
5758};
@@ -727,7 +728,7 @@ static int disas_alt_init(struct disas_alt *dalt,
727728}
728729
729730static int disas_alt_add_insn (struct disas_alt * dalt , int index , char * insn_str ,
730- int offset )
731+ int offset , int nops )
731732{
732733 int len ;
733734
@@ -740,6 +741,7 @@ static int disas_alt_add_insn(struct disas_alt *dalt, int index, char *insn_str,
740741 len = strlen (insn_str );
741742 dalt -> insn [index ].str = insn_str ;
742743 dalt -> insn [index ].offset = offset ;
744+ dalt -> insn [index ].nops = nops ;
743745 if (len > dalt -> width )
744746 dalt -> width = len ;
745747
@@ -752,6 +754,7 @@ static int disas_alt_jump(struct disas_alt *dalt)
752754 struct instruction * dest_insn ;
753755 char suffix [2 ] = { 0 };
754756 char * str ;
757+ int nops ;
755758
756759 orig_insn = dalt -> orig_insn ;
757760 dest_insn = dalt -> alt -> insn ;
@@ -762,14 +765,16 @@ static int disas_alt_jump(struct disas_alt *dalt)
762765 str = strfmt ("jmp%-3s %lx <%s+0x%lx>" , suffix ,
763766 dest_insn -> offset , dest_insn -> sym -> name ,
764767 dest_insn -> offset - dest_insn -> sym -> offset );
768+ nops = 0 ;
765769 } else {
766770 str = strfmt ("nop%d" , orig_insn -> len );
771+ nops = orig_insn -> len ;
767772 }
768773
769774 if (!str )
770775 return -1 ;
771776
772- disas_alt_add_insn (dalt , 0 , str , 0 );
777+ disas_alt_add_insn (dalt , 0 , str , 0 , nops );
773778
774779 return 1 ;
775780}
@@ -789,7 +794,7 @@ static int disas_alt_extable(struct disas_alt *dalt)
789794 if (!str )
790795 return -1 ;
791796
792- disas_alt_add_insn (dalt , 0 , str , 0 );
797+ disas_alt_add_insn (dalt , 0 , str , 0 , 0 );
793798
794799 return 1 ;
795800}
@@ -805,11 +810,13 @@ static int disas_alt_group(struct disas_context *dctx, struct disas_alt *dalt)
805810 int offset ;
806811 char * str ;
807812 int count ;
813+ int nops ;
808814 int err ;
809815
810816 file = dctx -> file ;
811817 count = 0 ;
812818 offset = 0 ;
819+ nops = 0 ;
813820
814821 alt_for_each_insn (file , DALT_GROUP (dalt ), insn ) {
815822
@@ -818,7 +825,8 @@ static int disas_alt_group(struct disas_context *dctx, struct disas_alt *dalt)
818825 if (!str )
819826 return -1 ;
820827
821- err = disas_alt_add_insn (dalt , count , str , offset );
828+ nops = insn -> type == INSN_NOP ? insn -> len : 0 ;
829+ err = disas_alt_add_insn (dalt , count , str , offset , nops );
822830 if (err )
823831 break ;
824832 offset += insn -> len ;
@@ -834,6 +842,7 @@ static int disas_alt_group(struct disas_context *dctx, struct disas_alt *dalt)
834842static int disas_alt_default (struct disas_context * dctx , struct disas_alt * dalt )
835843{
836844 char * str ;
845+ int nops ;
837846 int err ;
838847
839848 if (DALT_GROUP (dalt ))
@@ -849,7 +858,8 @@ static int disas_alt_default(struct disas_context *dctx, struct disas_alt *dalt)
849858 str = strdup (disas_result (dctx ));
850859 if (!str )
851860 return -1 ;
852- err = disas_alt_add_insn (dalt , 0 , str , 0 );
861+ nops = dalt -> orig_insn -> type == INSN_NOP ? dalt -> orig_insn -> len : 0 ;
862+ err = disas_alt_add_insn (dalt , 0 , str , 0 , nops );
853863 if (err )
854864 return -1 ;
855865
@@ -995,6 +1005,62 @@ static void disas_alt_print_compact(char *alt_name, struct disas_alt *dalts,
9951005 }
9961006}
9971007
1008+ /*
1009+ * Trim NOPs in alternatives. This replaces trailing NOPs in alternatives
1010+ * with a single indication of the number of bytes covered with NOPs.
1011+ *
1012+ * Return the maximum numbers of instructions in all alternatives after
1013+ * trailing NOPs have been trimmed.
1014+ */
1015+ static int disas_alt_trim_nops (struct disas_alt * dalts , int alt_count ,
1016+ int insn_count )
1017+ {
1018+ struct disas_alt * dalt ;
1019+ int nops_count ;
1020+ const char * s ;
1021+ int offset ;
1022+ int count ;
1023+ int nops ;
1024+ int i , j ;
1025+
1026+ count = 0 ;
1027+ for (i = 0 ; i < alt_count ; i ++ ) {
1028+ offset = 0 ;
1029+ nops = 0 ;
1030+ nops_count = 0 ;
1031+ dalt = & dalts [i ];
1032+ for (j = insn_count - 1 ; j >= 0 ; j -- ) {
1033+ if (!dalt -> insn [j ].str || !dalt -> insn [j ].nops )
1034+ break ;
1035+ offset = dalt -> insn [j ].offset ;
1036+ free (dalt -> insn [j ].str );
1037+ dalt -> insn [j ].offset = 0 ;
1038+ dalt -> insn [j ].str = NULL ;
1039+ nops += dalt -> insn [j ].nops ;
1040+ nops_count ++ ;
1041+ }
1042+
1043+ /*
1044+ * All trailing NOPs have been removed. If there was a single
1045+ * NOP instruction then re-add it. If there was a block of
1046+ * NOPs then indicate the number of bytes than the block
1047+ * covers (nop*<number-of-bytes>).
1048+ */
1049+ if (nops_count ) {
1050+ s = nops_count == 1 ? "" : "*" ;
1051+ dalt -> insn [j + 1 ].str = strfmt ("nop%s%d" , s , nops );
1052+ dalt -> insn [j + 1 ].offset = offset ;
1053+ dalt -> insn [j + 1 ].nops = nops ;
1054+ j ++ ;
1055+ }
1056+
1057+ if (j > count )
1058+ count = j ;
1059+ }
1060+
1061+ return count + 1 ;
1062+ }
1063+
9981064/*
9991065 * Disassemble an alternative.
10001066 *
@@ -1083,6 +1149,8 @@ static void *disas_alt(struct disas_context *dctx,
10831149 * Print default and non-default alternatives.
10841150 */
10851151
1152+ insn_count = disas_alt_trim_nops (dalts , alt_count , insn_count );
1153+
10861154 if (opts .wide )
10871155 disas_alt_print_wide (alt_name , dalts , alt_count , insn_count );
10881156 else
0 commit comments