forked from luck/tmp_suning_uos_patched
perf annotate: Add per arch instructions annotate handlers
Another step in supporting cross annotation. The arch specific tables are put in: tools/perf/arch/$ARCH/annotation/instructions.c which, so far, just plug instructions to a bunch of parsers/formatters, but may have more as the need arises. This is an alternative implementation to a previous attempt made by Ravi Bangoria. 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: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> 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-g3wt282lfa51j4qd0813e3az@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
9c2fb451bd
commit
763d8960a1
90
tools/perf/arch/arm/annotate/instructions.c
Normal file
90
tools/perf/arch/arm/annotate/instructions.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
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, },
|
||||
};
|
78
tools/perf/arch/x86/annotate/instructions.c
Normal file
78
tools/perf/arch/x86/annotate/instructions.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
static struct ins x86__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 = "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, },
|
||||
};
|
|
@ -28,20 +28,36 @@ const char *disassembler_style;
|
|||
const char *objdump_path;
|
||||
static regex_t file_lineno;
|
||||
|
||||
static struct ins *ins__find(const char *name);
|
||||
static struct ins *ins__find(struct arch *arch, const char *name);
|
||||
static int disasm_line__parse(char *line, char **namep, char **rawp);
|
||||
|
||||
struct arch {
|
||||
const char *name;
|
||||
struct ins *instructions;
|
||||
size_t nr_instructions;
|
||||
bool sorted_instructions;
|
||||
struct {
|
||||
char comment_char;
|
||||
char skip_functions_char;
|
||||
} objdump;
|
||||
};
|
||||
|
||||
static struct ins_ops call_ops;
|
||||
static struct ins_ops dec_ops;
|
||||
static struct ins_ops jump_ops;
|
||||
static struct ins_ops mov_ops;
|
||||
static struct ins_ops nop_ops;
|
||||
static struct ins_ops lock_ops;
|
||||
static struct ins_ops ret_ops;
|
||||
|
||||
#include "arch/arm/annotate/instructions.c"
|
||||
#include "arch/x86/annotate/instructions.c"
|
||||
|
||||
static struct arch architectures[] = {
|
||||
{
|
||||
.name = "arm",
|
||||
.instructions = arm__instructions,
|
||||
.nr_instructions = ARRAY_SIZE(arm__instructions),
|
||||
.objdump = {
|
||||
.comment_char = ';',
|
||||
.skip_functions_char = '+',
|
||||
|
@ -49,6 +65,8 @@ static struct arch architectures[] = {
|
|||
},
|
||||
{
|
||||
.name = "x86",
|
||||
.instructions = x86__instructions,
|
||||
.nr_instructions = ARRAY_SIZE(x86__instructions),
|
||||
.objdump = {
|
||||
.comment_char = '#',
|
||||
},
|
||||
|
@ -209,7 +227,7 @@ static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map *
|
|||
if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
|
||||
goto out_free_ops;
|
||||
|
||||
ops->locked.ins = ins__find(name);
|
||||
ops->locked.ins = ins__find(arch, name);
|
||||
free(name);
|
||||
|
||||
if (ops->locked.ins == NULL)
|
||||
|
@ -385,99 +403,6 @@ bool ins__is_ret(const struct ins *ins)
|
|||
return ins->ops == &ret_ops;
|
||||
}
|
||||
|
||||
static struct ins 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, },
|
||||
#ifdef __arm__
|
||||
{ .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, },
|
||||
#endif
|
||||
{ .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, },
|
||||
};
|
||||
|
||||
static int ins__key_cmp(const void *name, const void *insp)
|
||||
{
|
||||
const struct ins *ins = insp;
|
||||
|
@ -493,24 +418,23 @@ static int ins__cmp(const void *a, const void *b)
|
|||
return strcmp(ia->name, ib->name);
|
||||
}
|
||||
|
||||
static void ins__sort(void)
|
||||
static void ins__sort(struct arch *arch)
|
||||
{
|
||||
const int nmemb = ARRAY_SIZE(instructions);
|
||||
const int nmemb = arch->nr_instructions;
|
||||
|
||||
qsort(instructions, nmemb, sizeof(struct ins), ins__cmp);
|
||||
qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
|
||||
}
|
||||
|
||||
static struct ins *ins__find(const char *name)
|
||||
static struct ins *ins__find(struct arch *arch, const char *name)
|
||||
{
|
||||
const int nmemb = ARRAY_SIZE(instructions);
|
||||
static bool sorted;
|
||||
const int nmemb = arch->nr_instructions;
|
||||
|
||||
if (!sorted) {
|
||||
ins__sort();
|
||||
sorted = true;
|
||||
if (!arch->sorted_instructions) {
|
||||
ins__sort(arch);
|
||||
arch->sorted_instructions = true;
|
||||
}
|
||||
|
||||
return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp);
|
||||
return bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);
|
||||
}
|
||||
|
||||
static int arch__key_cmp(const void *name, const void *archp)
|
||||
|
@ -767,7 +691,7 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
|
|||
|
||||
static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map)
|
||||
{
|
||||
dl->ins = ins__find(dl->name);
|
||||
dl->ins = ins__find(arch, dl->name);
|
||||
|
||||
if (dl->ins == NULL)
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue
Block a user