99#include <objtool/arch.h>
1010#include <objtool/check.h>
1111#include <objtool/disas.h>
12+ #include <objtool/special.h>
1213#include <objtool/warn.h>
1314
1415#include <bfd.h>
@@ -60,6 +61,21 @@ struct disas_alt {
6061#define DALT_GROUP (dalt ) (DALT_INSN(dalt)->alt_group)
6162#define DALT_ALTID (dalt ) ((dalt)->orig_insn->offset)
6263
64+ #define ALT_FLAGS_SHIFT 16
65+ #define ALT_FLAG_NOT (1 << 0)
66+ #define ALT_FLAG_DIRECT_CALL (1 << 1)
67+ #define ALT_FEATURE_MASK ((1 << ALT_FLAGS_SHIFT) - 1)
68+
69+ static int alt_feature (unsigned int ft_flags )
70+ {
71+ return (ft_flags & ALT_FEATURE_MASK );
72+ }
73+
74+ static int alt_flags (unsigned int ft_flags )
75+ {
76+ return (ft_flags >> ALT_FLAGS_SHIFT );
77+ }
78+
6379/*
6480 * Wrapper around asprintf() to allocate and format a string.
6581 * Return the allocated string or NULL on error.
@@ -635,7 +651,12 @@ const char *disas_alt_type_name(struct instruction *insn)
635651 */
636652char * disas_alt_name (struct alternative * alt )
637653{
654+ char pfx [4 ] = { 0 };
638655 char * str = NULL ;
656+ const char * name ;
657+ int feature ;
658+ int flags ;
659+ int num ;
639660
640661 switch (alt -> type ) {
641662
@@ -649,13 +670,37 @@ char *disas_alt_name(struct alternative *alt)
649670
650671 case ALT_TYPE_INSTRUCTIONS :
651672 /*
652- * This is a non-default group alternative. Create a unique
653- * name using the offset of the first original and alternative
654- * instructions.
673+ * This is a non-default group alternative. Create a name
674+ * based on the feature and flags associated with this
675+ * alternative. Use either the feature name (it is available)
676+ * or the feature number. And add a prefix to show the flags
677+ * used.
678+ *
679+ * Prefix flags characters:
680+ *
681+ * '!' alternative used when feature not enabled
682+ * '+' direct call alternative
683+ * '?' unknown flag
655684 */
656- asprintf (& str , "ALTERNATIVE %lx.%lx" ,
657- alt -> insn -> alt_group -> orig_group -> first_insn -> offset ,
658- alt -> insn -> alt_group -> first_insn -> offset );
685+
686+ feature = alt -> insn -> alt_group -> feature ;
687+ num = alt_feature (feature );
688+ flags = alt_flags (feature );
689+ str = pfx ;
690+
691+ if (flags & ~(ALT_FLAG_NOT | ALT_FLAG_DIRECT_CALL ))
692+ * str ++ = '?' ;
693+ if (flags & ALT_FLAG_DIRECT_CALL )
694+ * str ++ = '+' ;
695+ if (flags & ALT_FLAG_NOT )
696+ * str ++ = '!' ;
697+
698+ name = arch_cpu_feature_name (num );
699+ if (!name )
700+ str = strfmt ("%sFEATURE 0x%X" , pfx , num );
701+ else
702+ str = strfmt ("%s%s" , pfx , name );
703+
659704 break ;
660705 }
661706
@@ -892,6 +937,7 @@ static void *disas_alt(struct disas_context *dctx,
892937 WARN ("%s has more alternatives than supported" , alt_name );
893938 break ;
894939 }
940+
895941 dalt = & dalts [i ];
896942 err = disas_alt_init (dalt , orig_insn , alt );
897943 if (err ) {
0 commit comments