Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf annotate: Improve support for ARM

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>

+60 -96
+58 -89
tools/perf/arch/arm/annotate/instructions.c
··· 1 - static 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, }, 1 + #include <sys/types.h> 2 + #include <regex.h> 3 + 4 + struct arm_annotate { 5 + regex_t call_insn, 6 + jump_insn; 90 7 }; 8 + 9 + static struct ins_ops *arm__associate_instruction_ops(struct arch *arch, const char *name) 10 + { 11 + struct arm_annotate *arm = arch->priv; 12 + struct ins_ops *ops; 13 + regmatch_t match[2]; 14 + 15 + if (!regexec(&arm->call_insn, name, 2, match, 0)) 16 + ops = &call_ops; 17 + else if (!regexec(&arm->jump_insn, name, 2, match, 0)) 18 + ops = &jump_ops; 19 + else 20 + return NULL; 21 + 22 + arch__associate_ins_ops(arch, name, ops); 23 + return ops; 24 + } 25 + 26 + static int arm__annotate_init(struct arch *arch) 27 + { 28 + struct arm_annotate *arm; 29 + int err; 30 + 31 + if (arch->initialized) 32 + return 0; 33 + 34 + arm = zalloc(sizeof(*arm)); 35 + if (!arm) 36 + return -1; 37 + 38 + #define ARM_CONDS "(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl|vc|vs)" 39 + err = regcomp(&arm->call_insn, "^blx?" ARM_CONDS "?$", REG_EXTENDED); 40 + if (err) 41 + goto out_free_arm; 42 + err = regcomp(&arm->jump_insn, "^bx?" ARM_CONDS "?$", REG_EXTENDED); 43 + if (err) 44 + goto out_free_call; 45 + #undef ARM_CONDS 46 + 47 + arch->initialized = true; 48 + arch->priv = arm; 49 + arch->associate_instruction_ops = arm__associate_instruction_ops; 50 + arch->objdump.comment_char = ';'; 51 + arch->objdump.skip_functions_char = '+'; 52 + return 0; 53 + 54 + out_free_call: 55 + regfree(&arm->call_insn); 56 + out_free_arm: 57 + free(arm); 58 + return -1; 59 + }
+2 -7
tools/perf/util/annotate.c
··· 84 84 goto out_update_instructions; 85 85 } 86 86 87 - static __maybe_unused int arch__associate_ins_ops(struct arch* arch, const char *name, struct ins_ops *ops) 87 + static int arch__associate_ins_ops(struct arch* arch, const char *name, struct ins_ops *ops) 88 88 { 89 89 struct ins *ins; 90 90 ··· 110 110 static struct arch architectures[] = { 111 111 { 112 112 .name = "arm", 113 - .instructions = arm__instructions, 114 - .nr_instructions = ARRAY_SIZE(arm__instructions), 115 - .objdump = { 116 - .comment_char = ';', 117 - .skip_functions_char = '+', 118 - }, 113 + .init = arm__annotate_init, 119 114 }, 120 115 { 121 116 .name = "x86",