linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Kim Phillips <kim.phillips@arm.com>
To: Namhyung Kim <namhyung@kernel.org>
Cc: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	linuxppc-dev@lists.ozlabs.org,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Taeung Song <treeze.taeung@gmail.com>,
	"Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com>,
	markus@trippelsdorf.de, chris.ryder@arm.com,
	Pawel Moll <pawel.moll@arm.com>,
	Masami Hiramatsu <mhiramat@kernel.org>,
	rmk+kernel@arm.linux.org.uk, Jiri Olsa <jolsa@kernel.org>,
	Michael Ellerman <mpe@ellerman.id.au>,
	Hemant Kumar <hemant@linux.vnet.ibm.com>
Subject: Re: [PATCH v6 2/7] perf annotate: Add cross arch annotate support
Date: Tue, 23 Aug 2016 15:36:17 -0500	[thread overview]
Message-ID: <20160823153617.c0bb45eeefe993c554cb792a@arm.com> (raw)
In-Reply-To: <CAM9d7cgXL7vnFS32=2wGDkMry7cbeAe2N0NnmhJscvNA1vb4Vg@mail.gmail.com>

On Tue, 23 Aug 2016 11:17:16 +0900
Namhyung Kim <namhyung@kernel.org> wrote:

> On Tue, Aug 23, 2016 at 8:01 AM, Kim Phillips <kim.phillips@arm.com> wrote:
> > On Fri, 19 Aug 2016 18:29:33 +0530
> > Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
> >
> >> Changes in v6:
> >>   - Instead of adding only those instructions defined in #ifdef __arm__,
> >>     add all instructions from default table to arm table.
> > Thanks, I've gone through the list and removed all not-ARM
> > instructions, and added some missing ARM branch instructions:
> 
> Can we use regex patterns instead?

Yes, that helps prevent mistakes updating instruction lists - how does
this look?:

diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index b2c6cf3..52316f3 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -26,6 +26,7 @@
 const char 	*disassembler_style;
 const char	*objdump_path;
 static regex_t	 file_lineno;
+static regex_t	 arm_call_insn, arm_jump_insn;
 
 static struct ins *ins__find(const char *name, const char *norm_arch);
 static int disasm_line__parse(char *line, char **namep, char **rawp);
@@ -449,98 +450,7 @@ static struct ins instructions_x86[] = {
 	{ .name = "retq",  .ops  = &ret_ops, },
 };
 
-static struct ins instructions_arm[] = {
-	{ .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, },
-};
-
-struct instructions_powerpc {
+struct instructions_arch {
 	struct ins *ins;
 	struct list_head list;
 };
@@ -560,41 +470,41 @@ static int ins__cmp(const void *a, const void *b)
 	return strcmp(ia->name, ib->name);
 }
 
-static struct ins *list_add__ins_powerpc(struct instructions_powerpc *head,
+static struct ins *list_add__ins_arch(struct instructions_arch *head,
 					 const char *name, struct ins_ops *ops)
 {
-	struct instructions_powerpc *ins_powerpc;
+	struct instructions_arch *ins_arch;
 	struct ins *ins;
 
 	ins = zalloc(sizeof(struct ins));
 	if (!ins)
 		return NULL;
 
-	ins_powerpc = zalloc(sizeof(struct instructions_powerpc));
-	if (!ins_powerpc)
+	ins_arch = zalloc(sizeof(struct instructions_arch));
+	if (!ins_arch)
 		goto out_free_ins;
 
 	ins->name = strdup(name);
 	if (!ins->name)
-		goto out_free_ins_power;
+		goto out_free_ins_arch;
 
 	ins->ops = ops;
-	ins_powerpc->ins = ins;
-	list_add_tail(&(ins_powerpc->list), &(head->list));
+	ins_arch->ins = ins;
+	list_add_tail(&(ins_arch->list), &(head->list));
 
 	return ins;
 
-out_free_ins_power:
-	zfree(&ins_powerpc);
+out_free_ins_arch:
+	zfree(&ins_arch);
 out_free_ins:
 	zfree(&ins);
 	return NULL;
 }
 
-static struct ins *list_search__ins_powerpc(struct instructions_powerpc *head,
+static struct ins *list_search__ins_arch(struct instructions_arch *head,
 					    const char *name)
 {
-	struct instructions_powerpc *pos;
+	struct instructions_arch *pos;
 
 	list_for_each_entry(pos, &head->list, list) {
 		if (!strcmp(pos->ins->name, name))
@@ -608,7 +518,7 @@ static struct ins *ins__find_powerpc(const char *name)
 	int i;
 	struct ins *ins;
 	struct ins_ops *ops;
-	static struct instructions_powerpc head;
+	static struct instructions_arch head;
 	static bool list_initialized;
 
 	/*
@@ -629,7 +539,7 @@ static struct ins *ins__find_powerpc(const char *name)
 	/*
 	 * Return if we already have object of 'struct ins' for this instruction
 	 */
-	ins = list_search__ins_powerpc(&head, name);
+	ins = list_search__ins_arch(&head, name);
 	if (ins)
 		return ins;
 
@@ -666,7 +576,44 @@ static struct ins *ins__find_powerpc(const char *name)
 	 * Add instruction to list so next time no need to
 	 * allocate memory for it.
 	 */
-	return list_add__ins_powerpc(&head, name, ops);
+	return list_add__ins_arch(&head, name, ops);
+}
+
+static struct ins *ins__find_arm(const char *name)
+{
+	struct ins *ins;
+	struct ins_ops *ops = &mov_ops;
+	static struct instructions_arch head;
+	static bool list_initialized;
+	regmatch_t match[2];
+	int ret;
+
+	if (!list_initialized) {
+		INIT_LIST_HEAD(&head.list);
+		list_initialized = true;
+	}
+
+	/*
+	 * Return if we already have object of 'struct ins' for this instruction
+	 */
+	ins = list_search__ins_arch(&head, name);
+	if (ins)
+		return ins;
+
+	ret = regexec(&arm_call_insn, name, 2, match, 0);
+	if (!ret) {
+		ops = &call_ops;
+	} else {
+		ret = regexec(&arm_jump_insn, name, 2, match, 0);
+		if (!ret)
+			ops = &jump_ops;
+	}
+
+	/*
+	 * Add instruction to list so next time no need to
+	 * allocate memory for it.
+	 */
+	return list_add__ins_arch(&head, name, ops);
 }
 
 static void ins__sort(struct ins *instructions, int nmemb)
@@ -686,15 +633,26 @@ static const char *annotate__norm_arch(char *arch)
 	return normalize_arch(arch);
 }
 
+#define ARM_CONDS "(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl|vc|vs)"
+
 static struct ins *ins__find(const char *name, const char *norm_arch)
 {
 	static bool sorted;
 	struct ins *instructions;
-	int nmemb;
+	int nmemb, ret;
 
 	if (!sorted) {
 		ins__sort(instructions_x86, ARRAY_SIZE(instructions_x86));
-		ins__sort(instructions_arm, ARRAY_SIZE(instructions_arm));
+		if (!strcmp(norm_arch, NORM_ARM)) {
+			ret = regcomp(&arm_call_insn,
+				      "^blx?" ARM_CONDS "?$", REG_EXTENDED);
+			ret |= regcomp(&arm_jump_insn,
+				       "^bx?" ARM_CONDS "?$", REG_EXTENDED);
+			if (ret) {
+				pr_err("regcomp failed\n");
+				return NULL;
+			}
+		}
 		sorted = true;
 	}
 
@@ -702,8 +660,7 @@ static struct ins *ins__find(const char *name, const char *norm_arch)
 		instructions = instructions_x86;
 		nmemb = ARRAY_SIZE(instructions_x86);
 	} else if (!strcmp(norm_arch, NORM_ARM)) {
-		instructions = instructions_arm;
-		nmemb = ARRAY_SIZE(instructions_arm);
+		return ins__find_arm(name);
 	} else if (!strcmp(norm_arch, NORM_POWERPC)) {
 		return ins__find_powerpc(name);
 	} else {

Note that, for ARM, in order to match return instructions, 'lr' must be
found to be the operand of the branch instruction, which is not
contained in the 'name' variable passed to ins__find().

Kim

  reply	other threads:[~2016-08-23 20:36 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-19 12:59 [PATCH v6 0/7] perf: Cross arch annotate + few miscellaneous fixes Ravi Bangoria
2016-08-19 12:59 ` [PATCH v6 1/7] perf: Define macro for normalized arch names Ravi Bangoria
2016-08-19 12:59 ` [PATCH v6 2/7] perf annotate: Add cross arch annotate support Ravi Bangoria
2016-08-22 23:01   ` Kim Phillips
2016-08-23  2:17     ` Namhyung Kim
2016-08-23 20:36       ` Kim Phillips [this message]
2016-08-26  6:21         ` Namhyung Kim
2016-08-26  7:26         ` Ravi Bangoria
2016-08-27  0:40           ` [PATCH] perf annotate: cross arch annotate support fixes for ARM Kim Phillips
2016-08-19 12:59 ` [PATCH v6 3/7] perf annotate: Add support for powerpc Ravi Bangoria
2016-09-19 15:26   ` Arnaldo Carvalho de Melo
2016-08-19 12:59 ` [PATCH v6 4/7] perf annotate: Do not ignore call instruction with indirect target Ravi Bangoria
2016-09-19 15:44   ` Arnaldo Carvalho de Melo
2016-09-20 14:35     ` Ravi Bangoria
2016-09-20 14:56       ` Arnaldo Carvalho de Melo
2016-08-19 12:59 ` [PATCH v6 5/7] perf annotate: Show raw form for jump " Ravi Bangoria
2016-08-19 12:59 ` [PATCH v6 6/7] perf annotate: Support jump instruction with target as second operand Ravi Bangoria
2016-08-19 12:59 ` [PATCH v6 7/7] perf annotate: Fix jump target outside of function address range Ravi Bangoria
2016-09-07 15:39 ` [PATCH v6 0/7] perf: Cross arch annotate + few miscellaneous fixes Ravi Bangoria

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160823153617.c0bb45eeefe993c554cb792a@arm.com \
    --to=kim.phillips@arm.com \
    --cc=acme@kernel.org \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=chris.ryder@arm.com \
    --cc=hemant@linux.vnet.ibm.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=markus@trippelsdorf.de \
    --cc=mhiramat@kernel.org \
    --cc=mingo@redhat.com \
    --cc=mpe@ellerman.id.au \
    --cc=namhyung@kernel.org \
    --cc=naveen.n.rao@linux.vnet.ibm.com \
    --cc=pawel.moll@arm.com \
    --cc=peterz@infradead.org \
    --cc=ravi.bangoria@linux.vnet.ibm.com \
    --cc=rmk+kernel@arm.linux.org.uk \
    --cc=treeze.taeung@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).