Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753313AbcJJQYX (ORCPT ); Mon, 10 Oct 2016 12:24:23 -0400 Received: from mail.kernel.org ([198.145.29.136]:56634 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753294AbcJJQYV (ORCPT ); Mon, 10 Oct 2016 12:24:21 -0400 Date: Mon, 10 Oct 2016 13:24:12 -0300 From: Arnaldo Carvalho de Melo To: Ravi Bangoria Cc: linux-kernel@vger.kernel.org, peterz@infradead.org, mingo@redhat.com, alexander.shishkin@linux.intel.com, jolsa@redhat.com, hekuang@huawei.com, jpoimboe@redhat.com, eranian@google.com, adrian.hunter@intel.com, mhiramat@kernel.org, pawel.moll@arm.com, chris.ryder@arm.com, naveen.n.rao@linux.vnet.ibm.com Subject: Re: [PATCH] perf annotate: Cleanup arch specific stuff Message-ID: <20161010162412.GK4809@kernel.org> References: <1474472876-2706-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com> <1476107942-9200-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1476107942-9200-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com> X-Url: http://acmel.wordpress.com User-Agent: Mutt/1.7.0 (2016-08-17) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 22163 Lines: 678 Em Mon, Oct 10, 2016 at 07:29:02PM +0530, Ravi Bangoria escreveu: > Move arch specific stuff from util/annotate.c to their respective > files in util/annotate directory. > > No functionality changes. > > Signed-off-by: Ravi Bangoria > --- > tools/perf/util/Build | 1 + > tools/perf/util/annotate.c | 259 +++---------------------------------- > tools/perf/util/annotate.h | 23 ++++ > tools/perf/util/annotate/Build | 3 + > tools/perf/util/annotate/arm.c | 50 +++++++ > tools/perf/util/annotate/powerpc.c | 63 +++++++++ > tools/perf/util/annotate/x86.c | 107 +++++++++++++++ We already have a per arch area: tools/perf/arch/ - Arnaldo > 7 files changed, 264 insertions(+), 242 deletions(-) > create mode 100644 tools/perf/util/annotate/Build > create mode 100644 tools/perf/util/annotate/arm.c > create mode 100644 tools/perf/util/annotate/powerpc.c > create mode 100644 tools/perf/util/annotate/x86.c > > diff --git a/tools/perf/util/Build b/tools/perf/util/Build > index eb60e61..1ee1170 100644 > --- a/tools/perf/util/Build > +++ b/tools/perf/util/Build > @@ -1,4 +1,5 @@ > libperf-y += alias.o > +libperf-y += annotate/ > libperf-y += annotate.o > libperf-y += block-range.o > libperf-y += build-id.o > diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c > index 83d5ac8..a168d1e 100644 > --- a/tools/perf/util/annotate.c > +++ b/tools/perf/util/annotate.c > @@ -28,7 +28,6 @@ const char *disassembler_style; > const char *objdump_path; > static regex_t file_lineno; > static char *norm_arch; > -static regex_t arm_call_insn, arm_jump_insn; > > static struct ins *ins__find(const char *name); > static int disasm_line__parse(char *line, char **namep, char **rawp); > @@ -110,7 +109,7 @@ static int call__scnprintf(struct ins *ins, char *bf, size_t size, > return scnprintf(bf, size, "%-6.6s *%" PRIx64, ins->name, ops->target.addr); > } > > -static struct ins_ops call_ops = { > +struct ins_ops call_ops = { > .parse = call__parse, > .scnprintf = call__scnprintf, > }; > @@ -149,7 +148,7 @@ static int jump__scnprintf(struct ins *ins, char *bf, size_t size, > return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset); > } > > -static struct ins_ops jump_ops = { > +struct ins_ops jump_ops = { > .parse = jump__parse, > .scnprintf = jump__scnprintf, > }; > @@ -242,7 +241,7 @@ static void lock__delete(struct ins_operands *ops) > zfree(&ops->target.name); > } > > -static struct ins_ops lock_ops = { > +struct ins_ops lock_ops = { > .free = lock__delete, > .parse = lock__parse, > .scnprintf = lock__scnprintf, > @@ -306,7 +305,7 @@ static int mov__scnprintf(struct ins *ins, char *bf, size_t size, > ops->target.name ?: ops->target.raw); > } > > -static struct ins_ops mov_ops = { > +struct ins_ops mov_ops = { > .parse = mov__parse, > .scnprintf = mov__scnprintf, > }; > @@ -347,7 +346,7 @@ static int dec__scnprintf(struct ins *ins, char *bf, size_t size, > ops->target.name ?: ops->target.raw); > } > > -static struct ins_ops dec_ops = { > +struct ins_ops dec_ops = { > .parse = dec__parse, > .scnprintf = dec__scnprintf, > }; > @@ -358,11 +357,11 @@ static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size, > return scnprintf(bf, size, "%-6.6s", "nop"); > } > > -static struct ins_ops nop_ops = { > +struct ins_ops nop_ops = { > .scnprintf = nop__scnprintf, > }; > > -static struct ins_ops ret_ops = { > +struct ins_ops ret_ops = { > .scnprintf = ins__raw_scnprintf, > }; > > @@ -371,107 +370,8 @@ bool ins__is_ret(const struct ins *ins) > return ins->ops == &ret_ops; > } > > -static struct ins instructions_x86[] = { > - { .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, }, > -}; > - > -struct instructions_arch { > - struct ins *ins; > - struct list_head list; > -}; > - > -static int ins__key_cmp(const void *name, const void *insp) > -{ > - const struct ins *ins = insp; > - > - return strcmp(name, ins->name); > -} > - > -static int ins__cmp(const void *a, const void *b) > -{ > - const struct ins *ia = a; > - const struct ins *ib = b; > - > - return strcmp(ia->name, ib->name); > -} > - > -static struct ins *list_add__ins_arch(struct instructions_arch *head, > - const char *name, struct ins_ops *ops) > +struct ins *list_add__ins_arch(struct instructions_arch *head, > + const char *name, struct ins_ops *ops) > { > struct instructions_arch *ins_arch; > struct ins *ins; > @@ -501,8 +401,8 @@ static struct ins *list_add__ins_arch(struct instructions_arch *head, > return NULL; > } > > -static struct ins *list_search__ins_arch(struct instructions_arch *head, > - const char *name) > +struct ins *list_search__ins_arch(struct instructions_arch *head, > + const char *name) > { > struct instructions_arch *pos; > > @@ -513,106 +413,6 @@ static struct ins *list_search__ins_arch(struct instructions_arch *head, > return NULL; > } > > -static struct ins *ins__find_powerpc(const char *name) > -{ > - int i; > - struct ins *ins; > - struct ins_ops *ops; > - static struct instructions_arch head = { > - .list = LIST_HEAD_INIT(head.list), > - }; > - > - /* > - * - Interested only if instruction starts with 'b'. > - * - Few start with 'b', but aren't branch instructions. > - */ > - if (name[0] != 'b' || > - !strncmp(name, "bcd", 3) || > - !strncmp(name, "brinc", 5) || > - !strncmp(name, "bper", 4)) > - return NULL; > - > - /* > - * Return if we already have object of 'struct ins' for this instruction > - */ > - ins = list_search__ins_arch(&head, name); > - if (ins) > - return ins; > - > - ops = &jump_ops; > - > - 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-")) > - ops = &call_ops; > - } > - if (name[i] == 'r' && name[i-1] == 'l') > - /* > - * instructions ending with 'lr' are considered to be > - * return instructions > - */ > - ops = &ret_ops; > - > - /* > - * Add instruction to list so next time no need to > - * allocate memory for it. > - */ > - 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; > - regmatch_t match[2]; > - int ret; > - static struct instructions_arch head = { > - .list = LIST_HEAD_INIT(head.list), > - }; > - > - /* > - * 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) > -{ > - qsort(instructions, nmemb, sizeof(struct ins), ins__cmp); > -} > - > static const char *annotate__norm_arch(char *arch) > { > struct utsname uts; > @@ -625,43 +425,18 @@ 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) > { > - static bool sorted; > - struct ins *instructions; > - int nmemb, ret; > - > - if (!sorted) { > - ins__sort(instructions_x86, ARRAY_SIZE(instructions_x86)); > - if (!strcmp(norm_arch, "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; > - } > - > - if (!strcmp(norm_arch, "x86")) { > - instructions = instructions_x86; > - nmemb = ARRAY_SIZE(instructions_x86); > - } else if (!strcmp(norm_arch, "arm")) { > + if (!strcmp(norm_arch, "x86")) > + return ins__find_x86(name); > + else if (!strcmp(norm_arch, "arm")) > return ins__find_arm(name); > - } else if (!strcmp(norm_arch, "powerpc")) { > + else if (!strcmp(norm_arch, "powerpc")) > return ins__find_powerpc(name); > - } else { > + else > pr_err("perf annotate not supported by %s arch\n", norm_arch); > - return NULL; > - } > > - return bsearch(name, instructions, nmemb, sizeof(struct ins), > - ins__key_cmp); > + return NULL; > } > > int symbol__alloc_hist(struct symbol *sym) > diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h > index 7ba3579..91b705a 100644 > --- a/tools/perf/util/annotate.h > +++ b/tools/perf/util/annotate.h > @@ -42,11 +42,30 @@ struct ins_ops { > struct ins_operands *ops); > }; > > +/* Defined in annotate.c */ > +extern struct ins_ops mov_ops; > +extern struct ins_ops call_ops; > +extern struct ins_ops dec_ops; > +extern struct ins_ops jump_ops; > +extern struct ins_ops lock_ops; > +extern struct ins_ops nop_ops; > +extern struct ins_ops ret_ops; > + > struct ins { > const char *name; > struct ins_ops *ops; > }; > > +struct instructions_arch { > + struct ins *ins; > + struct list_head list; > +}; > + > +struct ins *list_add__ins_arch(struct instructions_arch *head, > + const char *name, struct ins_ops *ops); > +struct ins *list_search__ins_arch(struct instructions_arch *head, > + const char *name); > + > bool ins__is_jump(const struct ins *ins); > bool ins__is_call(const struct ins *ins); > bool ins__is_ret(const struct ins *ins); > @@ -210,4 +229,8 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, > > extern const char *disassembler_style; > > +struct ins *ins__find_x86(const char *name); > +struct ins *ins__find_arm(const char *name); > +struct ins *ins__find_powerpc(const char *name); > + > #endif /* __PERF_ANNOTATE_H */ > diff --git a/tools/perf/util/annotate/Build b/tools/perf/util/annotate/Build > new file mode 100644 > index 0000000..ed87f1c > --- /dev/null > +++ b/tools/perf/util/annotate/Build > @@ -0,0 +1,3 @@ > +libperf-y += x86.o > +libperf-y += arm.o > +libperf-y += powerpc.o > diff --git a/tools/perf/util/annotate/arm.c b/tools/perf/util/annotate/arm.c > new file mode 100644 > index 0000000..6bfc866 > --- /dev/null > +++ b/tools/perf/util/annotate/arm.c > @@ -0,0 +1,50 @@ > +#include "../annotate.h" > + > +static regex_t arm_call_insn, arm_jump_insn; > + > +#define ARM_CONDS "(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl|vc|vs)" > + > +static __attribute__((constructor)) void init_regex(void) > +{ > + int ret; > + > + 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"); > +} > + > +struct ins *ins__find_arm(const char *name) > +{ > + struct ins *ins; > + struct ins_ops *ops = &mov_ops; > + regmatch_t match[2]; > + int ret; > + static struct instructions_arch head = { > + .list = LIST_HEAD_INIT(head.list), > + }; > + > + /* > + * 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); > + > +} > diff --git a/tools/perf/util/annotate/powerpc.c b/tools/perf/util/annotate/powerpc.c > new file mode 100644 > index 0000000..6088ce2 > --- /dev/null > +++ b/tools/perf/util/annotate/powerpc.c > @@ -0,0 +1,63 @@ > +#include "../annotate.h" > + > +struct ins *ins__find_powerpc(const char *name) > +{ > + int i; > + struct ins *ins; > + struct ins_ops *ops; > + static struct instructions_arch head = { > + .list = LIST_HEAD_INIT(head.list), > + }; > + > + /* > + * - Interested only if instruction starts with 'b'. > + * - Few start with 'b', but aren't branch instructions. > + */ > + if (name[0] != 'b' || > + !strncmp(name, "bcd", 3) || > + !strncmp(name, "brinc", 5) || > + !strncmp(name, "bper", 4)) > + return NULL; > + > + /* > + * Return if we already have object of 'struct ins' for this instruction > + */ > + ins = list_search__ins_arch(&head, name); > + if (ins) > + return ins; > + > + ops = &jump_ops; > + > + 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-")) > + ops = &call_ops; > + } > + if (name[i] == 'r' && name[i-1] == 'l') > + /* > + * instructions ending with 'lr' are considered to be > + * return instructions > + */ > + ops = &ret_ops; > + > + /* > + * Add instruction to list so next time no need to > + * allocate memory for it. > + */ > + return list_add__ins_arch(&head, name, ops); > +} > diff --git a/tools/perf/util/annotate/x86.c b/tools/perf/util/annotate/x86.c > new file mode 100644 > index 0000000..b519197 > --- /dev/null > +++ b/tools/perf/util/annotate/x86.c > @@ -0,0 +1,107 @@ > +#include "../annotate.h" > + > +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, }, > + { .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__cmp(const void *a, const void *b) > +{ > + const struct ins *ia = a; > + const struct ins *ib = b; > + > + return strcmp(ia->name, ib->name); > +} > + > +static __attribute__((constructor)) void ins__sort(void) > +{ > + qsort(instructions, ARRAY_SIZE(instructions), sizeof(struct ins), > + ins__cmp); > +} > + > +static int ins__key_cmp(const void *name, const void *insp) > +{ > + const struct ins *ins = insp; > + > + return strcmp(name, ins->name); > +} > + > +struct ins *ins__find_x86(const char *name) > +{ > + return bsearch(name, instructions, ARRAY_SIZE(instructions), > + sizeof(struct ins), ins__key_cmp); > +} > -- > 2.5.5