aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/arch/arm/annotate/instructions.c90
-rw-r--r--tools/perf/arch/x86/annotate/instructions.c78
-rw-r--r--tools/perf/util/annotate.c136
3 files changed, 198 insertions, 106 deletions
diff --git a/tools/perf/arch/arm/annotate/instructions.c b/tools/perf/arch/arm/annotate/instructions.c
new file mode 100644
index 000000000000..d67b8aa26274
--- /dev/null
+++ b/tools/perf/arch/arm/annotate/instructions.c
@@ -0,0 +1,90 @@
1static struct ins arm__instructions[] = {
2 { .name = "add", .ops = &mov_ops, },
3 { .name = "addl", .ops = &mov_ops, },
4 { .name = "addq", .ops = &mov_ops, },
5 { .name = "addw", .ops = &mov_ops, },
6 { .name = "and", .ops = &mov_ops, },
7 { .name = "b", .ops = &jump_ops, }, // might also be a call
8 { .name = "bcc", .ops = &jump_ops, },
9 { .name = "bcs", .ops = &jump_ops, },
10 { .name = "beq", .ops = &jump_ops, },
11 { .name = "bge", .ops = &jump_ops, },
12 { .name = "bgt", .ops = &jump_ops, },
13 { .name = "bhi", .ops = &jump_ops, },
14 { .name = "bl", .ops = &call_ops, },
15 { .name = "bls", .ops = &jump_ops, },
16 { .name = "blt", .ops = &jump_ops, },
17 { .name = "blx", .ops = &call_ops, },
18 { .name = "bne", .ops = &jump_ops, },
19 { .name = "bts", .ops = &mov_ops, },
20 { .name = "call", .ops = &call_ops, },
21 { .name = "callq", .ops = &call_ops, },
22 { .name = "cmp", .ops = &mov_ops, },
23 { .name = "cmpb", .ops = &mov_ops, },
24 { .name = "cmpl", .ops = &mov_ops, },
25 { .name = "cmpq", .ops = &mov_ops, },
26 { .name = "cmpw", .ops = &mov_ops, },
27 { .name = "cmpxch", .ops = &mov_ops, },
28 { .name = "dec", .ops = &dec_ops, },
29 { .name = "decl", .ops = &dec_ops, },
30 { .name = "imul", .ops = &mov_ops, },
31 { .name = "inc", .ops = &dec_ops, },
32 { .name = "incl", .ops = &dec_ops, },
33 { .name = "ja", .ops = &jump_ops, },
34 { .name = "jae", .ops = &jump_ops, },
35 { .name = "jb", .ops = &jump_ops, },
36 { .name = "jbe", .ops = &jump_ops, },
37 { .name = "jc", .ops = &jump_ops, },
38 { .name = "jcxz", .ops = &jump_ops, },
39 { .name = "je", .ops = &jump_ops, },
40 { .name = "jecxz", .ops = &jump_ops, },
41 { .name = "jg", .ops = &jump_ops, },
42 { .name = "jge", .ops = &jump_ops, },
43 { .name = "jl", .ops = &jump_ops, },
44 { .name = "jle", .ops = &jump_ops, },
45 { .name = "jmp", .ops = &jump_ops, },
46 { .name = "jmpq", .ops = &jump_ops, },
47 { .name = "jna", .ops = &jump_ops, },
48 { .name = "jnae", .ops = &jump_ops, },
49 { .name = "jnb", .ops = &jump_ops, },
50 { .name = "jnbe", .ops = &jump_ops, },
51 { .name = "jnc", .ops = &jump_ops, },
52 { .name = "jne", .ops = &jump_ops, },
53 { .name = "jng", .ops = &jump_ops, },
54 { .name = "jnge", .ops = &jump_ops, },
55 { .name = "jnl", .ops = &jump_ops, },
56 { .name = "jnle", .ops = &jump_ops, },
57 { .name = "jno", .ops = &jump_ops, },
58 { .name = "jnp", .ops = &jump_ops, },
59 { .name = "jns", .ops = &jump_ops, },
60 { .name = "jnz", .ops = &jump_ops, },
61 { .name = "jo", .ops = &jump_ops, },
62 { .name = "jp", .ops = &jump_ops, },
63 { .name = "jpe", .ops = &jump_ops, },
64 { .name = "jpo", .ops = &jump_ops, },
65 { .name = "jrcxz", .ops = &jump_ops, },
66 { .name = "js", .ops = &jump_ops, },
67 { .name = "jz", .ops = &jump_ops, },
68 { .name = "lea", .ops = &mov_ops, },
69 { .name = "lock", .ops = &lock_ops, },
70 { .name = "mov", .ops = &mov_ops, },
71 { .name = "movb", .ops = &mov_ops, },
72 { .name = "movdqa", .ops = &mov_ops, },
73 { .name = "movl", .ops = &mov_ops, },
74 { .name = "movq", .ops = &mov_ops, },
75 { .name = "movslq", .ops = &mov_ops, },
76 { .name = "movzbl", .ops = &mov_ops, },
77 { .name = "movzwl", .ops = &mov_ops, },
78 { .name = "nop", .ops = &nop_ops, },
79 { .name = "nopl", .ops = &nop_ops, },
80 { .name = "nopw", .ops = &nop_ops, },
81 { .name = "or", .ops = &mov_ops, },
82 { .name = "orl", .ops = &mov_ops, },
83 { .name = "test", .ops = &mov_ops, },
84 { .name = "testb", .ops = &mov_ops, },
85 { .name = "testl", .ops = &mov_ops, },
86 { .name = "xadd", .ops = &mov_ops, },
87 { .name = "xbeginl", .ops = &jump_ops, },
88 { .name = "xbeginq", .ops = &jump_ops, },
89 { .name = "retq", .ops = &ret_ops, },
90};
diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c
new file mode 100644
index 000000000000..c1625f256df3
--- /dev/null
+++ b/tools/perf/arch/x86/annotate/instructions.c
@@ -0,0 +1,78 @@
1static struct ins x86__instructions[] = {
2 { .name = "add", .ops = &mov_ops, },
3 { .name = "addl", .ops = &mov_ops, },
4 { .name = "addq", .ops = &mov_ops, },
5 { .name = "addw", .ops = &mov_ops, },
6 { .name = "and", .ops = &mov_ops, },
7 { .name = "bts", .ops = &mov_ops, },
8 { .name = "call", .ops = &call_ops, },
9 { .name = "callq", .ops = &call_ops, },
10 { .name = "cmp", .ops = &mov_ops, },
11 { .name = "cmpb", .ops = &mov_ops, },
12 { .name = "cmpl", .ops = &mov_ops, },
13 { .name = "cmpq", .ops = &mov_ops, },
14 { .name = "cmpw", .ops = &mov_ops, },
15 { .name = "cmpxch", .ops = &mov_ops, },
16 { .name = "dec", .ops = &dec_ops, },
17 { .name = "decl", .ops = &dec_ops, },
18 { .name = "imul", .ops = &mov_ops, },
19 { .name = "inc", .ops = &dec_ops, },
20 { .name = "incl", .ops = &dec_ops, },
21 { .name = "ja", .ops = &jump_ops, },
22 { .name = "jae", .ops = &jump_ops, },
23 { .name = "jb", .ops = &jump_ops, },
24 { .name = "jbe", .ops = &jump_ops, },
25 { .name = "jc", .ops = &jump_ops, },
26 { .name = "jcxz", .ops = &jump_ops, },
27 { .name = "je", .ops = &jump_ops, },
28 { .name = "jecxz", .ops = &jump_ops, },
29 { .name = "jg", .ops = &jump_ops, },
30 { .name = "jge", .ops = &jump_ops, },
31 { .name = "jl", .ops = &jump_ops, },
32 { .name = "jle", .ops = &jump_ops, },
33 { .name = "jmp", .ops = &jump_ops, },
34 { .name = "jmpq", .ops = &jump_ops, },
35 { .name = "jna", .ops = &jump_ops, },
36 { .name = "jnae", .ops = &jump_ops, },
37 { .name = "jnb", .ops = &jump_ops, },
38 { .name = "jnbe", .ops = &jump_ops, },
39 { .name = "jnc", .ops = &jump_ops, },
40 { .name = "jne", .ops = &jump_ops, },
41 { .name = "jng", .ops = &jump_ops, },
42 { .name = "jnge", .ops = &jump_ops, },
43 { .name = "jnl", .ops = &jump_ops, },
44 { .name = "jnle", .ops = &jump_ops, },
45 { .name = "jno", .ops = &jump_ops, },
46 { .name = "jnp", .ops = &jump_ops, },
47 { .name = "jns", .ops = &jump_ops, },
48 { .name = "jnz", .ops = &jump_ops, },
49 { .name = "jo", .ops = &jump_ops, },
50 { .name = "jp", .ops = &jump_ops, },
51 { .name = "jpe", .ops = &jump_ops, },
52 { .name = "jpo", .ops = &jump_ops, },
53 { .name = "jrcxz", .ops = &jump_ops, },
54 { .name = "js", .ops = &jump_ops, },
55 { .name = "jz", .ops = &jump_ops, },
56 { .name = "lea", .ops = &mov_ops, },
57 { .name = "lock", .ops = &lock_ops, },
58 { .name = "mov", .ops = &mov_ops, },
59 { .name = "movb", .ops = &mov_ops, },
60 { .name = "movdqa", .ops = &mov_ops, },
61 { .name = "movl", .ops = &mov_ops, },
62 { .name = "movq", .ops = &mov_ops, },
63 { .name = "movslq", .ops = &mov_ops, },
64 { .name = "movzbl", .ops = &mov_ops, },
65 { .name = "movzwl", .ops = &mov_ops, },
66 { .name = "nop", .ops = &nop_ops, },
67 { .name = "nopl", .ops = &nop_ops, },
68 { .name = "nopw", .ops = &nop_ops, },
69 { .name = "or", .ops = &mov_ops, },
70 { .name = "orl", .ops = &mov_ops, },
71 { .name = "test", .ops = &mov_ops, },
72 { .name = "testb", .ops = &mov_ops, },
73 { .name = "testl", .ops = &mov_ops, },
74 { .name = "xadd", .ops = &mov_ops, },
75 { .name = "xbeginl", .ops = &jump_ops, },
76 { .name = "xbeginq", .ops = &jump_ops, },
77 { .name = "retq", .ops = &ret_ops, },
78};
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 72769762ece9..095d90a9077f 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -28,20 +28,36 @@ const char *disassembler_style;
28const char *objdump_path; 28const char *objdump_path;
29static regex_t file_lineno; 29static regex_t file_lineno;
30 30
31static struct ins *ins__find(const char *name); 31static struct ins *ins__find(struct arch *arch, const char *name);
32static int disasm_line__parse(char *line, char **namep, char **rawp); 32static int disasm_line__parse(char *line, char **namep, char **rawp);
33 33
34struct arch { 34struct arch {
35 const char *name; 35 const char *name;
36 struct ins *instructions;
37 size_t nr_instructions;
38 bool sorted_instructions;
36 struct { 39 struct {
37 char comment_char; 40 char comment_char;
38 char skip_functions_char; 41 char skip_functions_char;
39 } objdump; 42 } objdump;
40}; 43};
41 44
45static struct ins_ops call_ops;
46static struct ins_ops dec_ops;
47static struct ins_ops jump_ops;
48static struct ins_ops mov_ops;
49static struct ins_ops nop_ops;
50static struct ins_ops lock_ops;
51static struct ins_ops ret_ops;
52
53#include "arch/arm/annotate/instructions.c"
54#include "arch/x86/annotate/instructions.c"
55
42static struct arch architectures[] = { 56static struct arch architectures[] = {
43 { 57 {
44 .name = "arm", 58 .name = "arm",
59 .instructions = arm__instructions,
60 .nr_instructions = ARRAY_SIZE(arm__instructions),
45 .objdump = { 61 .objdump = {
46 .comment_char = ';', 62 .comment_char = ';',
47 .skip_functions_char = '+', 63 .skip_functions_char = '+',
@@ -49,6 +65,8 @@ static struct arch architectures[] = {
49 }, 65 },
50 { 66 {
51 .name = "x86", 67 .name = "x86",
68 .instructions = x86__instructions,
69 .nr_instructions = ARRAY_SIZE(x86__instructions),
52 .objdump = { 70 .objdump = {
53 .comment_char = '#', 71 .comment_char = '#',
54 }, 72 },
@@ -209,7 +227,7 @@ static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map *
209 if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0) 227 if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
210 goto out_free_ops; 228 goto out_free_ops;
211 229
212 ops->locked.ins = ins__find(name); 230 ops->locked.ins = ins__find(arch, name);
213 free(name); 231 free(name);
214 232
215 if (ops->locked.ins == NULL) 233 if (ops->locked.ins == NULL)
@@ -385,99 +403,6 @@ bool ins__is_ret(const struct ins *ins)
385 return ins->ops == &ret_ops; 403 return ins->ops == &ret_ops;
386} 404}
387 405
388static struct ins instructions[] = {
389 { .name = "add", .ops = &mov_ops, },
390 { .name = "addl", .ops = &mov_ops, },
391 { .name = "addq", .ops = &mov_ops, },
392 { .name = "addw", .ops = &mov_ops, },
393 { .name = "and", .ops = &mov_ops, },
394#ifdef __arm__
395 { .name = "b", .ops = &jump_ops, }, // might also be a call
396 { .name = "bcc", .ops = &jump_ops, },
397 { .name = "bcs", .ops = &jump_ops, },
398 { .name = "beq", .ops = &jump_ops, },
399 { .name = "bge", .ops = &jump_ops, },
400 { .name = "bgt", .ops = &jump_ops, },
401 { .name = "bhi", .ops = &jump_ops, },
402 { .name = "bl", .ops = &call_ops, },
403 { .name = "bls", .ops = &jump_ops, },
404 { .name = "blt", .ops = &jump_ops, },
405 { .name = "blx", .ops = &call_ops, },
406 { .name = "bne", .ops = &jump_ops, },
407#endif
408 { .name = "bts", .ops = &mov_ops, },
409 { .name = "call", .ops = &call_ops, },
410 { .name = "callq", .ops = &call_ops, },
411 { .name = "cmp", .ops = &mov_ops, },
412 { .name = "cmpb", .ops = &mov_ops, },
413 { .name = "cmpl", .ops = &mov_ops, },
414 { .name = "cmpq", .ops = &mov_ops, },
415 { .name = "cmpw", .ops = &mov_ops, },
416 { .name = "cmpxch", .ops = &mov_ops, },
417 { .name = "dec", .ops = &dec_ops, },
418 { .name = "decl", .ops = &dec_ops, },
419 { .name = "imul", .ops = &mov_ops, },
420 { .name = "inc", .ops = &dec_ops, },
421 { .name = "incl", .ops = &dec_ops, },
422 { .name = "ja", .ops = &jump_ops, },
423 { .name = "jae", .ops = &jump_ops, },
424 { .name = "jb", .ops = &jump_ops, },
425 { .name = "jbe", .ops = &jump_ops, },
426 { .name = "jc", .ops = &jump_ops, },
427 { .name = "jcxz", .ops = &jump_ops, },
428 { .name = "je", .ops = &jump_ops, },
429 { .name = "jecxz", .ops = &jump_ops, },
430 { .name = "jg", .ops = &jump_ops, },
431 { .name = "jge", .ops = &jump_ops, },
432 { .name = "jl", .ops = &jump_ops, },
433 { .name = "jle", .ops = &jump_ops, },
434 { .name = "jmp", .ops = &jump_ops, },
435 { .name = "jmpq", .ops = &jump_ops, },
436 { .name = "jna", .ops = &jump_ops, },
437 { .name = "jnae", .ops = &jump_ops, },
438 { .name = "jnb", .ops = &jump_ops, },
439 { .name = "jnbe", .ops = &jump_ops, },
440 { .name = "jnc", .ops = &jump_ops, },
441 { .name = "jne", .ops = &jump_ops, },
442 { .name = "jng", .ops = &jump_ops, },
443 { .name = "jnge", .ops = &jump_ops, },
444 { .name = "jnl", .ops = &jump_ops, },
445 { .name = "jnle", .ops = &jump_ops, },
446 { .name = "jno", .ops = &jump_ops, },
447 { .name = "jnp", .ops = &jump_ops, },
448 { .name = "jns", .ops = &jump_ops, },
449 { .name = "jnz", .ops = &jump_ops, },
450 { .name = "jo", .ops = &jump_ops, },
451 { .name = "jp", .ops = &jump_ops, },
452 { .name = "jpe", .ops = &jump_ops, },
453 { .name = "jpo", .ops = &jump_ops, },
454 { .name = "jrcxz", .ops = &jump_ops, },
455 { .name = "js", .ops = &jump_ops, },
456 { .name = "jz", .ops = &jump_ops, },
457 { .name = "lea", .ops = &mov_ops, },
458 { .name = "lock", .ops = &lock_ops, },
459 { .name = "mov", .ops = &mov_ops, },
460 { .name = "movb", .ops = &mov_ops, },
461 { .name = "movdqa",.ops = &mov_ops, },
462 { .name = "movl", .ops = &mov_ops, },
463 { .name = "movq", .ops = &mov_ops, },
464 { .name = "movslq", .ops = &mov_ops, },
465 { .name = "movzbl", .ops = &mov_ops, },
466 { .name = "movzwl", .ops = &mov_ops, },
467 { .name = "nop", .ops = &nop_ops, },
468 { .name = "nopl", .ops = &nop_ops, },
469 { .name = "nopw", .ops = &nop_ops, },
470 { .name = "or", .ops = &mov_ops, },
471 { .name = "orl", .ops = &mov_ops, },
472 { .name = "test", .ops = &mov_ops, },
473 { .name = "testb", .ops = &mov_ops, },
474 { .name = "testl", .ops = &mov_ops, },
475 { .name = "xadd", .ops = &mov_ops, },
476 { .name = "xbeginl", .ops = &jump_ops, },
477 { .name = "xbeginq", .ops = &jump_ops, },
478 { .name = "retq", .ops = &ret_ops, },
479};
480
481static int ins__key_cmp(const void *name, const void *insp) 406static int ins__key_cmp(const void *name, const void *insp)
482{ 407{
483 const struct ins *ins = insp; 408 const struct ins *ins = insp;
@@ -493,24 +418,23 @@ static int ins__cmp(const void *a, const void *b)
493 return strcmp(ia->name, ib->name); 418 return strcmp(ia->name, ib->name);
494} 419}
495 420
496static void ins__sort(void) 421static void ins__sort(struct arch *arch)
497{ 422{
498 const int nmemb = ARRAY_SIZE(instructions); 423 const int nmemb = arch->nr_instructions;
499 424
500 qsort(instructions, nmemb, sizeof(struct ins), ins__cmp); 425 qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
501} 426}
502 427
503static struct ins *ins__find(const char *name) 428static struct ins *ins__find(struct arch *arch, const char *name)
504{ 429{
505 const int nmemb = ARRAY_SIZE(instructions); 430 const int nmemb = arch->nr_instructions;
506 static bool sorted;
507 431
508 if (!sorted) { 432 if (!arch->sorted_instructions) {
509 ins__sort(); 433 ins__sort(arch);
510 sorted = true; 434 arch->sorted_instructions = true;
511 } 435 }
512 436
513 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp); 437 return bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);
514} 438}
515 439
516static int arch__key_cmp(const void *name, const void *archp) 440static 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)
767 691
768static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map) 692static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map)
769{ 693{
770 dl->ins = ins__find(dl->name); 694 dl->ins = ins__find(arch, dl->name);
771 695
772 if (dl->ins == NULL) 696 if (dl->ins == NULL)
773 return; 697 return;