From: "Naveen N. Rao" <naveen.n....@linux.vnet.ibm.com> Powerpc has long list of branch instructions and hardcoding them in table appears to be error-prone. So, add new function to find instruction instead of creating table.
Signed-off-by: Naveen N. Rao <naveen.n....@linux.vnet.ibm.com> Signed-off-by: Ravi Bangoria <ravi.bango...@linux.vnet.ibm.com> --- tools/perf/util/annotate.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 634daf5..ad01825 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -492,6 +492,68 @@ static struct ins *ins__find(const char *name) sizeof(struct ins), ins__key_cmp); } +static struct ins *ins__find_powerpc(const char *name) +{ + int i; + struct ins *ins; + + ins = zalloc(sizeof(struct ins)); + if (!ins) + return NULL; + + ins->name = strdup(name); + if (!ins->name) + return NULL; + + if (name[0] == 'b') { + /* branch instructions */ + ins->ops = &jump_ops; + + /* + * - Few start with 'b', but aren't branch instructions. + * - Let's also ignore instructions involving 'ctr' and + * 'tar' since target branch addresses for those can't + * be determined statically. + */ + if (!strncmp(name, "bcd", 3) || + !strncmp(name, "brinc", 5) || + !strncmp(name, "bper", 4) || + strstr(name, "ctr") || + strstr(name, "tar")) + return NULL; + + i = strlen(name) - 1; + if (i < 0) + return NULL; + + /* ignore optional hints at the end of the instructions */ + if (name[i] == '+' || name[i] == '-') + i--; + + if (name[i] == 'l' || (name[i] == 'a' && name[i-1] == 'l')) { + /* + * if the instruction ends up with 'l' or 'la', then + * those are considered 'calls' since they update LR. + * ... except for 'bnl' which is branch if not less than + * and the absolute form of the same. + */ + if (strcmp(name, "bnl") && strcmp(name, "bnl+") && + strcmp(name, "bnl-") && strcmp(name, "bnla") && + strcmp(name, "bnla+") && strcmp(name, "bnla-")) + ins->ops = &call_ops; + } + if (name[i] == 'r' && name[i-1] == 'l') + /* + * instructions ending with 'lr' are considered to be + * return instructions + */ + ins->ops = &ret_ops; + + return ins; + } + return NULL; +} + static void __init_arch_ins(const char *arch, struct ins *instructions, int size, struct ins *(*func)(const char *)) { @@ -513,6 +575,8 @@ static int _init_arch_ins(const char *norm_arch) __init_arch_ins(norm_arch, instructions_arm, ARRAY_SIZE(instructions_arm), ins__find); + else if (!strcmp(norm_arch, PERF_ARCH_POWERPC)) + __init_arch_ins(norm_arch, NULL, 0, ins__find_powerpc); else return -1; -- 2.5.5