perf annotate: Improve support for ARM
authorArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 18 Nov 2016 19:54:10 +0000 (16:54 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 25 Nov 2016 13:38:56 +0000 (10:38 -0300)
By using arch->init() to set up some regular expressions to associate
ins_ops to ARM instructions, ditching that old table that has
instructions not present on ARM.

Take advantage of having an arch->init() to hide more arm specific stuff
from the common code, like the objdump details.

The regular expressions comes from a patch written by Kim Phillips.

Reviewed-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Chris Riyder <chris.ryder@arm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kim Phillips <kim.phillips@arm.com>
Cc: Markus Trippelsdorf <markus@trippelsdorf.de>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Taeung Song <treeze.taeung@gmail.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/n/tip-77m7lufz9ajjimkrebtg5ead@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/arch/arm/annotate/instructions.c
tools/perf/util/annotate.c

index d67b8aa..1ce0872 100644 (file)
@@ -1,90 +1,59 @@
-static struct ins arm__instructions[] = {
-       { .name = "add",        .ops = &mov_ops,  },
-       { .name = "addl",       .ops = &mov_ops,  },
-       { .name = "addq",       .ops = &mov_ops,  },
-       { .name = "addw",       .ops = &mov_ops,  },
-       { .name = "and",        .ops = &mov_ops,  },
-       { .name = "b",          .ops = &jump_ops, }, // might also be a call
-       { .name = "bcc",        .ops = &jump_ops, },
-       { .name = "bcs",        .ops = &jump_ops, },
-       { .name = "beq",        .ops = &jump_ops, },
-       { .name = "bge",        .ops = &jump_ops, },
-       { .name = "bgt",        .ops = &jump_ops, },
-       { .name = "bhi",        .ops = &jump_ops, },
-       { .name = "bl",         .ops = &call_ops, },
-       { .name = "bls",        .ops = &jump_ops, },
-       { .name = "blt",        .ops = &jump_ops, },
-       { .name = "blx",        .ops = &call_ops, },
-       { .name = "bne",        .ops = &jump_ops, },
-       { .name = "bts",        .ops = &mov_ops,  },
-       { .name = "call",       .ops = &call_ops, },
-       { .name = "callq",      .ops = &call_ops, },
-       { .name = "cmp",        .ops = &mov_ops,  },
-       { .name = "cmpb",       .ops = &mov_ops,  },
-       { .name = "cmpl",       .ops = &mov_ops,  },
-       { .name = "cmpq",       .ops = &mov_ops,  },
-       { .name = "cmpw",       .ops = &mov_ops,  },
-       { .name = "cmpxch",     .ops = &mov_ops,  },
-       { .name = "dec",        .ops = &dec_ops,  },
-       { .name = "decl",       .ops = &dec_ops,  },
-       { .name = "imul",       .ops = &mov_ops,  },
-       { .name = "inc",        .ops = &dec_ops,  },
-       { .name = "incl",       .ops = &dec_ops,  },
-       { .name = "ja",         .ops = &jump_ops, },
-       { .name = "jae",        .ops = &jump_ops, },
-       { .name = "jb",         .ops = &jump_ops, },
-       { .name = "jbe",        .ops = &jump_ops, },
-       { .name = "jc",         .ops = &jump_ops, },
-       { .name = "jcxz",       .ops = &jump_ops, },
-       { .name = "je",         .ops = &jump_ops, },
-       { .name = "jecxz",      .ops = &jump_ops, },
-       { .name = "jg",         .ops = &jump_ops, },
-       { .name = "jge",        .ops = &jump_ops, },
-       { .name = "jl",         .ops = &jump_ops, },
-       { .name = "jle",        .ops = &jump_ops, },
-       { .name = "jmp",        .ops = &jump_ops, },
-       { .name = "jmpq",       .ops = &jump_ops, },
-       { .name = "jna",        .ops = &jump_ops, },
-       { .name = "jnae",       .ops = &jump_ops, },
-       { .name = "jnb",        .ops = &jump_ops, },
-       { .name = "jnbe",       .ops = &jump_ops, },
-       { .name = "jnc",        .ops = &jump_ops, },
-       { .name = "jne",        .ops = &jump_ops, },
-       { .name = "jng",        .ops = &jump_ops, },
-       { .name = "jnge",       .ops = &jump_ops, },
-       { .name = "jnl",        .ops = &jump_ops, },
-       { .name = "jnle",       .ops = &jump_ops, },
-       { .name = "jno",        .ops = &jump_ops, },
-       { .name = "jnp",        .ops = &jump_ops, },
-       { .name = "jns",        .ops = &jump_ops, },
-       { .name = "jnz",        .ops = &jump_ops, },
-       { .name = "jo",         .ops = &jump_ops, },
-       { .name = "jp",         .ops = &jump_ops, },
-       { .name = "jpe",        .ops = &jump_ops, },
-       { .name = "jpo",        .ops = &jump_ops, },
-       { .name = "jrcxz",      .ops = &jump_ops, },
-       { .name = "js",         .ops = &jump_ops, },
-       { .name = "jz",         .ops = &jump_ops, },
-       { .name = "lea",        .ops = &mov_ops,  },
-       { .name = "lock",       .ops = &lock_ops, },
-       { .name = "mov",        .ops = &mov_ops,  },
-       { .name = "movb",       .ops = &mov_ops,  },
-       { .name = "movdqa",     .ops = &mov_ops,  },
-       { .name = "movl",       .ops = &mov_ops,  },
-       { .name = "movq",       .ops = &mov_ops,  },
-       { .name = "movslq",     .ops = &mov_ops,  },
-       { .name = "movzbl",     .ops = &mov_ops,  },
-       { .name = "movzwl",     .ops = &mov_ops,  },
-       { .name = "nop",        .ops = &nop_ops,  },
-       { .name = "nopl",       .ops = &nop_ops,  },
-       { .name = "nopw",       .ops = &nop_ops,  },
-       { .name = "or",         .ops = &mov_ops,  },
-       { .name = "orl",        .ops = &mov_ops,  },
-       { .name = "test",       .ops = &mov_ops,  },
-       { .name = "testb",      .ops = &mov_ops,  },
-       { .name = "testl",      .ops = &mov_ops,  },
-       { .name = "xadd",       .ops = &mov_ops,  },
-       { .name = "xbeginl",    .ops = &jump_ops, },
-       { .name = "xbeginq",    .ops = &jump_ops, },
-       { .name = "retq",       .ops = &ret_ops,  },
+#include <sys/types.h>
+#include <regex.h>
+
+struct arm_annotate {
+       regex_t call_insn,
+               jump_insn;
 };
+
+static struct ins_ops *arm__associate_instruction_ops(struct arch *arch, const char *name)
+{
+       struct arm_annotate *arm = arch->priv;
+       struct ins_ops *ops;
+       regmatch_t match[2];
+
+       if (!regexec(&arm->call_insn, name, 2, match, 0))
+               ops = &call_ops;
+       else if (!regexec(&arm->jump_insn, name, 2, match, 0))
+               ops = &jump_ops;
+       else
+               return NULL;
+
+       arch__associate_ins_ops(arch, name, ops);
+       return ops;
+}
+
+static int arm__annotate_init(struct arch *arch)
+{
+       struct arm_annotate *arm;
+       int err;
+
+       if (arch->initialized)
+               return 0;
+
+       arm = zalloc(sizeof(*arm));
+       if (!arm)
+               return -1;
+
+#define ARM_CONDS "(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl|vc|vs)"
+       err = regcomp(&arm->call_insn, "^blx?" ARM_CONDS "?$", REG_EXTENDED);
+       if (err)
+               goto out_free_arm;
+       err = regcomp(&arm->jump_insn, "^bx?" ARM_CONDS "?$", REG_EXTENDED);
+       if (err)
+               goto out_free_call;
+#undef ARM_CONDS
+
+       arch->initialized = true;
+       arch->priv        = arm;
+       arch->associate_instruction_ops   = arm__associate_instruction_ops;
+       arch->objdump.comment_char        = ';';
+       arch->objdump.skip_functions_char = '+';
+       return 0;
+
+out_free_call:
+       regfree(&arm->call_insn);
+out_free_arm:
+       free(arm);
+       return -1;
+}
index 1e96549..bad44db 100644 (file)
@@ -84,7 +84,7 @@ grow_from_non_allocated_table:
        goto out_update_instructions;
 }
 
-static __maybe_unused int arch__associate_ins_ops(struct arch* arch, const char *name, struct ins_ops *ops)
+static int arch__associate_ins_ops(struct arch* arch, const char *name, struct ins_ops *ops)
 {
        struct ins *ins;
 
@@ -110,12 +110,7 @@ static __maybe_unused int arch__associate_ins_ops(struct arch* arch, const char
 static struct arch architectures[] = {
        {
                .name = "arm",
-               .instructions = arm__instructions,
-               .nr_instructions = ARRAY_SIZE(arm__instructions),
-               .objdump =  {
-                       .comment_char = ';',
-                       .skip_functions_char = '+',
-               },
+               .init = arm__annotate_init,
        },
        {
                .name = "x86",