summaryrefslogtreecommitdiff
path: root/tools/perf/arch
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2026-01-22 13:35:12 -0800
committerArnaldo Carvalho de Melo <acme@redhat.com>2026-01-23 16:58:38 -0300
commit07b972ff09f45cfb7acd20cd9b3769c6975bc434 (patch)
treef8cecf6a6a63113dd96b4305a42ef5af5eecef2b /tools/perf/arch
parent9273085273103e5994952dc2725f1f0109af97d1 (diff)
downloadlwn-07b972ff09f45cfb7acd20cd9b3769c6975bc434.tar.gz
lwn-07b972ff09f45cfb7acd20cd9b3769c6975bc434.zip
perf disasm: Don't include C files from the arch directory
Move the arch instructions.c files into appropriately named files in annotate-arch in the util directory. Don't #include to compile the code, switch to building the files and fix up the #includes accordingly. Move powerpc specific disasm code out of disasm.c and into annotate-powerpc.c. Declarations and static removed as appropriate for the code to compile as separate compilation units. The e_machine and e_flags set up is moved to the disasm.c architectures array so that later patches can sort by them. Reviewed-by: James Clark <james.clark@linaro.org> Signed-off-by: Ian Rogers <irogers@google.com> Cc: Aditya Bodkhe <aditya.b1@linux.ibm.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Albert Ou <aou@eecs.berkeley.edu> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Alexandre Ghiti <alex@ghiti.fr> Cc: Athira Rajeev <atrajeev@linux.ibm.com> Cc: Bill Wendling <morbo@google.com> Cc: Dr. David Alan Gilbert <linux@treblig.org> Cc: Guo Ren <guoren@kernel.org> Cc: Howard Chu <howardchu95@gmail.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: John Garry <john.g.garry@oracle.com> Cc: Julia Lawall <Julia.Lawall@inria.fr> Cc: Justin Stitt <justinstitt@google.com> Cc: Krzysztof Łopatowski <krzysztof.m.lopatowski@gmail.com> Cc: Leo Yan <leo.yan@linux.dev> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Nathan Chancellor <nathan@kernel.org> Cc: Nick Desaulniers <nick.desaulniers+lkml@gmail.com> Cc: Palmer Dabbelt <palmer@dabbelt.com> Cc: Paul Walmsley <pjw@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Sergei Trofimovich <slyich@gmail.com> Cc: Shimin Guo <shimin.guo@skydio.com> Cc: Suchit Karunakaran <suchitkarunakaran@gmail.com> Cc: Thomas Falcon <thomas.falcon@intel.com> Cc: Tianyou Li <tianyou.li@intel.com> Cc: Will Deacon <will@kernel.org> Cc: Zecheng Li <zecheng@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/arch')
-rw-r--r--tools/perf/arch/arc/annotate/instructions.c11
-rw-r--r--tools/perf/arch/arm/annotate/instructions.c66
-rw-r--r--tools/perf/arch/arm64/annotate/instructions.c126
-rw-r--r--tools/perf/arch/csky/annotate/instructions.c53
-rw-r--r--tools/perf/arch/loongarch/annotate/instructions.c145
-rw-r--r--tools/perf/arch/mips/annotate/instructions.c48
-rw-r--r--tools/perf/arch/powerpc/annotate/instructions.c317
-rw-r--r--tools/perf/arch/riscv64/annotate/instructions.c36
-rw-r--r--tools/perf/arch/s390/annotate/instructions.c178
-rw-r--r--tools/perf/arch/sparc/annotate/instructions.c171
-rw-r--r--tools/perf/arch/x86/annotate/instructions.c797
11 files changed, 0 insertions, 1948 deletions
diff --git a/tools/perf/arch/arc/annotate/instructions.c b/tools/perf/arch/arc/annotate/instructions.c
deleted file mode 100644
index e5619770a1af..000000000000
--- a/tools/perf/arch/arc/annotate/instructions.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/compiler.h>
-
-static int arc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
-{
- arch->initialized = true;
- arch->objdump.comment_char = ';';
- arch->e_machine = EM_ARC;
- arch->e_flags = 0;
- return 0;
-}
diff --git a/tools/perf/arch/arm/annotate/instructions.c b/tools/perf/arch/arm/annotate/instructions.c
deleted file mode 100644
index b997d127fedd..000000000000
--- a/tools/perf/arch/arm/annotate/instructions.c
+++ /dev/null
@@ -1,66 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/compiler.h>
-#include <linux/zalloc.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <regex.h>
-#include <stdlib.h>
-
-struct arm_annotate {
- regex_t call_insn,
- jump_insn;
-};
-
-static const struct ins_ops *arm__associate_instruction_ops(struct arch *arch, const char *name)
-{
- struct arm_annotate *arm = arch->priv;
- const struct ins_ops *ops;
- regmatch_t match[2];
-
- if (!regexec(&arm->call_insn, name, 2, match, 0))
- ops = &call_ops;
- else if (!regexec(&arm->jump_insn, name, 2, match, 0))
- ops = &jump_ops;
- else
- return NULL;
-
- arch__associate_ins_ops(arch, name, ops);
- return ops;
-}
-
-static int arm__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
-{
- struct arm_annotate *arm;
- int err;
-
- if (arch->initialized)
- return 0;
-
- arm = zalloc(sizeof(*arm));
- if (!arm)
- return ENOMEM;
-
-#define ARM_CONDS "(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl|vc|vs)"
- err = regcomp(&arm->call_insn, "^blx?" ARM_CONDS "?$", REG_EXTENDED);
- if (err)
- goto out_free_arm;
- err = regcomp(&arm->jump_insn, "^bx?" ARM_CONDS "?$", REG_EXTENDED);
- if (err)
- goto out_free_call;
-#undef ARM_CONDS
-
- arch->initialized = true;
- arch->priv = arm;
- arch->associate_instruction_ops = arm__associate_instruction_ops;
- arch->objdump.comment_char = ';';
- arch->objdump.skip_functions_char = '+';
- arch->e_machine = EM_ARM;
- arch->e_flags = 0;
- return 0;
-
-out_free_call:
- regfree(&arm->call_insn);
-out_free_arm:
- free(arm);
- return SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP;
-}
diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
deleted file mode 100644
index 44db33854dba..000000000000
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ /dev/null
@@ -1,126 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/compiler.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <regex.h>
-#include <stdlib.h>
-
-struct arm64_annotate {
- regex_t call_insn,
- jump_insn;
-};
-
-static int arm64_mov__parse(const struct arch *arch __maybe_unused,
- struct ins_operands *ops,
- struct map_symbol *ms __maybe_unused,
- struct disasm_line *dl __maybe_unused)
-{
- char *s = strchr(ops->raw, ','), *target, *endptr;
-
- if (s == NULL)
- return -1;
-
- *s = '\0';
- ops->source.raw = strdup(ops->raw);
- *s = ',';
-
- if (ops->source.raw == NULL)
- return -1;
-
- target = ++s;
- ops->target.raw = strdup(target);
- if (ops->target.raw == NULL)
- goto out_free_source;
-
- ops->target.addr = strtoull(target, &endptr, 16);
- if (endptr == target)
- goto out_free_target;
-
- s = strchr(endptr, '<');
- if (s == NULL)
- goto out_free_target;
- endptr = strchr(s + 1, '>');
- if (endptr == NULL)
- goto out_free_target;
-
- *endptr = '\0';
- *s = ' ';
- ops->target.name = strdup(s);
- *s = '<';
- *endptr = '>';
- if (ops->target.name == NULL)
- goto out_free_target;
-
- return 0;
-
-out_free_target:
- zfree(&ops->target.raw);
-out_free_source:
- zfree(&ops->source.raw);
- return -1;
-}
-
-static int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
- struct ins_operands *ops, int max_ins_name);
-
-static const struct ins_ops arm64_mov_ops = {
- .parse = arm64_mov__parse,
- .scnprintf = mov__scnprintf,
-};
-
-static const struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
-{
- struct arm64_annotate *arm = arch->priv;
- const struct ins_ops *ops;
- regmatch_t match[2];
-
- if (!regexec(&arm->jump_insn, name, 2, match, 0))
- ops = &jump_ops;
- else if (!regexec(&arm->call_insn, name, 2, match, 0))
- ops = &call_ops;
- else if (!strcmp(name, "ret"))
- ops = &ret_ops;
- else
- ops = &arm64_mov_ops;
-
- arch__associate_ins_ops(arch, name, ops);
- return ops;
-}
-
-static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
-{
- struct arm64_annotate *arm;
- int err;
-
- if (arch->initialized)
- return 0;
-
- arm = zalloc(sizeof(*arm));
- if (!arm)
- return ENOMEM;
-
- /* bl, blr */
- err = regcomp(&arm->call_insn, "^blr?$", REG_EXTENDED);
- if (err)
- goto out_free_arm;
- /* b, b.cond, br, cbz/cbnz, tbz/tbnz */
- err = regcomp(&arm->jump_insn, "^[ct]?br?\\.?(cc|cs|eq|ge|gt|hi|hs|le|lo|ls|lt|mi|ne|pl|vc|vs)?n?z?$",
- REG_EXTENDED);
- if (err)
- goto out_free_call;
-
- arch->initialized = true;
- arch->priv = arm;
- arch->associate_instruction_ops = arm64__associate_instruction_ops;
- arch->objdump.comment_char = '/';
- arch->objdump.skip_functions_char = '+';
- arch->e_machine = EM_AARCH64;
- arch->e_flags = 0;
- return 0;
-
-out_free_call:
- regfree(&arm->call_insn);
-out_free_arm:
- free(arm);
- return SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP;
-}
diff --git a/tools/perf/arch/csky/annotate/instructions.c b/tools/perf/arch/csky/annotate/instructions.c
deleted file mode 100644
index 4a55c84a320a..000000000000
--- a/tools/perf/arch/csky/annotate/instructions.c
+++ /dev/null
@@ -1,53 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
-
-#include <linux/compiler.h>
-
-static const struct ins_ops *csky__associate_ins_ops(struct arch *arch,
- const char *name)
-{
- const struct ins_ops *ops = NULL;
-
- /* catch all kind of jumps */
- if (!strcmp(name, "bt") ||
- !strcmp(name, "bf") ||
- !strcmp(name, "bez") ||
- !strcmp(name, "bnez") ||
- !strcmp(name, "bnezad") ||
- !strcmp(name, "bhsz") ||
- !strcmp(name, "bhz") ||
- !strcmp(name, "blsz") ||
- !strcmp(name, "blz") ||
- !strcmp(name, "br") ||
- !strcmp(name, "jmpi") ||
- !strcmp(name, "jmp"))
- ops = &jump_ops;
-
- /* catch function call */
- if (!strcmp(name, "bsr") ||
- !strcmp(name, "jsri") ||
- !strcmp(name, "jsr"))
- ops = &call_ops;
-
- /* catch function return */
- if (!strcmp(name, "rts"))
- ops = &ret_ops;
-
- if (ops)
- arch__associate_ins_ops(arch, name, ops);
- return ops;
-}
-
-static int csky__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
-{
- arch->initialized = true;
- arch->objdump.comment_char = '/';
- arch->associate_instruction_ops = csky__associate_ins_ops;
- arch->e_machine = EM_CSKY;
-#if defined(__CSKYABIV2__)
- arch->e_flags = EF_CSKY_ABIV2;
-#else
- arch->e_flags = EF_CSKY_ABIV1;
-#endif
- return 0;
-}
diff --git a/tools/perf/arch/loongarch/annotate/instructions.c b/tools/perf/arch/loongarch/annotate/instructions.c
deleted file mode 100644
index 5010d5d58375..000000000000
--- a/tools/perf/arch/loongarch/annotate/instructions.c
+++ /dev/null
@@ -1,145 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Perf annotate functions.
- *
- * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
- */
-
-static int loongarch_call__parse(const struct arch *arch, struct ins_operands *ops,
- struct map_symbol *ms,
- struct disasm_line *dl __maybe_unused)
-
-{
- char *c, *endptr, *tok, *name;
- struct map *map = ms->map;
- struct addr_map_symbol target;
-
- c = strchr(ops->raw, '#');
- if (c++ == NULL)
- return -1;
-
- ops->target.addr = strtoull(c, &endptr, 16);
-
- name = strchr(endptr, '<');
- name++;
-
- if (arch->objdump.skip_functions_char &&
- strchr(name, arch->objdump.skip_functions_char))
- return -1;
-
- tok = strchr(name, '>');
- if (tok == NULL)
- return -1;
-
- *tok = '\0';
- ops->target.name = strdup(name);
- *tok = '>';
-
- if (ops->target.name == NULL)
- return -1;
-
- target = (struct addr_map_symbol) {
- .ms = { .map = map__get(map), },
- .addr = map__objdump_2mem(map, ops->target.addr),
- };
-
- if (maps__find_ams(ms->maps, &target) == 0 &&
- map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
- ops->target.sym = target.ms.sym;
-
- addr_map_symbol__exit(&target);
- return 0;
-}
-
-static const struct ins_ops loongarch_call_ops = {
- .parse = loongarch_call__parse,
- .scnprintf = call__scnprintf,
-};
-
-static int loongarch_jump__parse(const struct arch *arch, struct ins_operands *ops,
- struct map_symbol *ms,
- struct disasm_line *dl __maybe_unused)
-
-{
- struct map *map = ms->map;
- struct symbol *sym = ms->sym;
- struct addr_map_symbol target = {
- .ms = { .map = map__get(map), },
- };
- const char *c = strchr(ops->raw, '#');
- u64 start, end;
-
- ops->jump.raw_comment = strchr(ops->raw, arch->objdump.comment_char);
- ops->jump.raw_func_start = strchr(ops->raw, '<');
-
- if (ops->jump.raw_func_start && c > ops->jump.raw_func_start)
- c = NULL;
-
- if (c++ != NULL)
- ops->target.addr = strtoull(c, NULL, 16);
- else
- ops->target.addr = strtoull(ops->raw, NULL, 16);
-
- target.addr = map__objdump_2mem(map, ops->target.addr);
- start = map__unmap_ip(map, sym->start);
- end = map__unmap_ip(map, sym->end);
-
- ops->target.outside = target.addr < start || target.addr > end;
-
- if (maps__find_ams(ms->maps, &target) == 0 &&
- map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
- ops->target.sym = target.ms.sym;
-
- if (!ops->target.outside) {
- ops->target.offset = target.addr - start;
- ops->target.offset_avail = true;
- } else {
- ops->target.offset_avail = false;
- }
- addr_map_symbol__exit(&target);
- return 0;
-}
-
-static const struct ins_ops loongarch_jump_ops = {
- .parse = loongarch_jump__parse,
- .scnprintf = jump__scnprintf,
-};
-
-static
-const struct ins_ops *loongarch__associate_ins_ops(struct arch *arch, const char *name)
-{
- const struct ins_ops *ops = NULL;
-
- if (!strcmp(name, "bl"))
- ops = &loongarch_call_ops;
- else if (!strcmp(name, "jirl"))
- ops = &ret_ops;
- else if (!strcmp(name, "b") ||
- !strncmp(name, "beq", 3) ||
- !strncmp(name, "bne", 3) ||
- !strncmp(name, "blt", 3) ||
- !strncmp(name, "bge", 3) ||
- !strncmp(name, "bltu", 4) ||
- !strncmp(name, "bgeu", 4))
- ops = &loongarch_jump_ops;
- else
- return NULL;
-
- arch__associate_ins_ops(arch, name, ops);
-
- return ops;
-}
-
-static
-int loongarch__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
-{
- if (!arch->initialized) {
- arch->associate_instruction_ops = loongarch__associate_ins_ops;
- arch->initialized = true;
- arch->objdump.comment_char = '#';
- arch->e_machine = EM_LOONGARCH;
- arch->e_flags = 0;
- }
-
- return 0;
-}
diff --git a/tools/perf/arch/mips/annotate/instructions.c b/tools/perf/arch/mips/annotate/instructions.c
deleted file mode 100644
index 0fbe0a7df95a..000000000000
--- a/tools/perf/arch/mips/annotate/instructions.c
+++ /dev/null
@@ -1,48 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-static
-const struct ins_ops *mips__associate_ins_ops(struct arch *arch, const char *name)
-{
- const struct ins_ops *ops = NULL;
-
- if (!strncmp(name, "bal", 3) ||
- !strncmp(name, "bgezal", 6) ||
- !strncmp(name, "bltzal", 6) ||
- !strncmp(name, "bgtzal", 6) ||
- !strncmp(name, "blezal", 6) ||
- !strncmp(name, "beqzal", 6) ||
- !strncmp(name, "bnezal", 6) ||
- !strncmp(name, "bgtzl", 5) ||
- !strncmp(name, "bltzl", 5) ||
- !strncmp(name, "bgezl", 5) ||
- !strncmp(name, "blezl", 5) ||
- !strncmp(name, "jialc", 5) ||
- !strncmp(name, "beql", 4) ||
- !strncmp(name, "bnel", 4) ||
- !strncmp(name, "jal", 3))
- ops = &call_ops;
- else if (!strncmp(name, "jr", 2))
- ops = &ret_ops;
- else if (name[0] == 'j' || name[0] == 'b')
- ops = &jump_ops;
- else
- return NULL;
-
- arch__associate_ins_ops(arch, name, ops);
-
- return ops;
-}
-
-static
-int mips__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
-{
- if (!arch->initialized) {
- arch->associate_instruction_ops = mips__associate_ins_ops;
- arch->initialized = true;
- arch->objdump.comment_char = '#';
- arch->e_machine = EM_MIPS;
- arch->e_flags = 0;
- }
-
- return 0;
-}
diff --git a/tools/perf/arch/powerpc/annotate/instructions.c b/tools/perf/arch/powerpc/annotate/instructions.c
deleted file mode 100644
index d1be55425e35..000000000000
--- a/tools/perf/arch/powerpc/annotate/instructions.c
+++ /dev/null
@@ -1,317 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/compiler.h>
-
-static const struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name)
-{
- int i;
- const struct ins_ops *ops;
-
- /*
- * - 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;
-
- 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;
-
- arch__associate_ins_ops(arch, name, ops);
- return ops;
-}
-
-#define PPC_OP(op) (((op) >> 26) & 0x3F)
-#define PPC_21_30(R) (((R) >> 1) & 0x3ff)
-#define PPC_22_30(R) (((R) >> 1) & 0x1ff)
-
-struct insn_offset {
- const char *name;
- int value;
-};
-
-/*
- * There are memory instructions with opcode 31 which are
- * of X Form, Example:
- * ldx RT,RA,RB
- * ______________________________________
- * | 31 | RT | RA | RB | 21 |/|
- * --------------------------------------
- * 0 6 11 16 21 30 31
- *
- * But all instructions with opcode 31 are not memory.
- * Example: add RT,RA,RB
- *
- * Use bits 21 to 30 to check memory insns with 31 as opcode.
- * In ins_array below, for ldx instruction:
- * name => OP_31_XOP_LDX
- * value => 21
- */
-
-static struct insn_offset ins_array[] = {
- { .name = "OP_31_XOP_LXSIWZX", .value = 12, },
- { .name = "OP_31_XOP_LWARX", .value = 20, },
- { .name = "OP_31_XOP_LDX", .value = 21, },
- { .name = "OP_31_XOP_LWZX", .value = 23, },
- { .name = "OP_31_XOP_LDUX", .value = 53, },
- { .name = "OP_31_XOP_LWZUX", .value = 55, },
- { .name = "OP_31_XOP_LXSIWAX", .value = 76, },
- { .name = "OP_31_XOP_LDARX", .value = 84, },
- { .name = "OP_31_XOP_LBZX", .value = 87, },
- { .name = "OP_31_XOP_LVX", .value = 103, },
- { .name = "OP_31_XOP_LBZUX", .value = 119, },
- { .name = "OP_31_XOP_STXSIWX", .value = 140, },
- { .name = "OP_31_XOP_STDX", .value = 149, },
- { .name = "OP_31_XOP_STWX", .value = 151, },
- { .name = "OP_31_XOP_STDUX", .value = 181, },
- { .name = "OP_31_XOP_STWUX", .value = 183, },
- { .name = "OP_31_XOP_STBX", .value = 215, },
- { .name = "OP_31_XOP_STVX", .value = 231, },
- { .name = "OP_31_XOP_STBUX", .value = 247, },
- { .name = "OP_31_XOP_LHZX", .value = 279, },
- { .name = "OP_31_XOP_LHZUX", .value = 311, },
- { .name = "OP_31_XOP_LXVDSX", .value = 332, },
- { .name = "OP_31_XOP_LWAX", .value = 341, },
- { .name = "OP_31_XOP_LHAX", .value = 343, },
- { .name = "OP_31_XOP_LWAUX", .value = 373, },
- { .name = "OP_31_XOP_LHAUX", .value = 375, },
- { .name = "OP_31_XOP_STHX", .value = 407, },
- { .name = "OP_31_XOP_STHUX", .value = 439, },
- { .name = "OP_31_XOP_LXSSPX", .value = 524, },
- { .name = "OP_31_XOP_LDBRX", .value = 532, },
- { .name = "OP_31_XOP_LSWX", .value = 533, },
- { .name = "OP_31_XOP_LWBRX", .value = 534, },
- { .name = "OP_31_XOP_LFSUX", .value = 567, },
- { .name = "OP_31_XOP_LXSDX", .value = 588, },
- { .name = "OP_31_XOP_LSWI", .value = 597, },
- { .name = "OP_31_XOP_LFDX", .value = 599, },
- { .name = "OP_31_XOP_LFDUX", .value = 631, },
- { .name = "OP_31_XOP_STXSSPX", .value = 652, },
- { .name = "OP_31_XOP_STDBRX", .value = 660, },
- { .name = "OP_31_XOP_STXWX", .value = 661, },
- { .name = "OP_31_XOP_STWBRX", .value = 662, },
- { .name = "OP_31_XOP_STFSX", .value = 663, },
- { .name = "OP_31_XOP_STFSUX", .value = 695, },
- { .name = "OP_31_XOP_STXSDX", .value = 716, },
- { .name = "OP_31_XOP_STSWI", .value = 725, },
- { .name = "OP_31_XOP_STFDX", .value = 727, },
- { .name = "OP_31_XOP_STFDUX", .value = 759, },
- { .name = "OP_31_XOP_LXVW4X", .value = 780, },
- { .name = "OP_31_XOP_LHBRX", .value = 790, },
- { .name = "OP_31_XOP_LXVD2X", .value = 844, },
- { .name = "OP_31_XOP_LFIWAX", .value = 855, },
- { .name = "OP_31_XOP_LFIWZX", .value = 887, },
- { .name = "OP_31_XOP_STXVW4X", .value = 908, },
- { .name = "OP_31_XOP_STHBRX", .value = 918, },
- { .name = "OP_31_XOP_STXVD2X", .value = 972, },
- { .name = "OP_31_XOP_STFIWX", .value = 983, },
-};
-
-/*
- * Arithmetic instructions which are having opcode as 31.
- * These instructions are tracked to save the register state
- * changes. Example:
- *
- * lwz r10,264(r3)
- * add r31, r3, r3
- * lwz r9, 0(r31)
- *
- * Here instruction tracking needs to identify the "add"
- * instruction and save data type of r3 to r31. If a sample
- * is hit at next "lwz r9, 0(r31)", by this instruction tracking,
- * data type of r31 can be resolved.
- */
-static struct insn_offset arithmetic_ins_op_31[] = {
- { .name = "SUB_CARRY_XO_FORM", .value = 8, },
- { .name = "MUL_HDW_XO_FORM1", .value = 9, },
- { .name = "ADD_CARRY_XO_FORM", .value = 10, },
- { .name = "MUL_HW_XO_FORM1", .value = 11, },
- { .name = "SUB_XO_FORM", .value = 40, },
- { .name = "MUL_HDW_XO_FORM", .value = 73, },
- { .name = "MUL_HW_XO_FORM", .value = 75, },
- { .name = "SUB_EXT_XO_FORM", .value = 136, },
- { .name = "ADD_EXT_XO_FORM", .value = 138, },
- { .name = "SUB_ZERO_EXT_XO_FORM", .value = 200, },
- { .name = "ADD_ZERO_EXT_XO_FORM", .value = 202, },
- { .name = "SUB_EXT_XO_FORM2", .value = 232, },
- { .name = "MUL_DW_XO_FORM", .value = 233, },
- { .name = "ADD_EXT_XO_FORM2", .value = 234, },
- { .name = "MUL_W_XO_FORM", .value = 235, },
- { .name = "ADD_XO_FORM", .value = 266, },
- { .name = "DIV_DW_XO_FORM1", .value = 457, },
- { .name = "DIV_W_XO_FORM1", .value = 459, },
- { .name = "DIV_DW_XO_FORM", .value = 489, },
- { .name = "DIV_W_XO_FORM", .value = 491, },
-};
-
-static struct insn_offset arithmetic_two_ops[] = {
- { .name = "mulli", .value = 7, },
- { .name = "subfic", .value = 8, },
- { .name = "addic", .value = 12, },
- { .name = "addic.", .value = 13, },
- { .name = "addi", .value = 14, },
- { .name = "addis", .value = 15, },
-};
-
-static int cmp_offset(const void *a, const void *b)
-{
- const struct insn_offset *val1 = a;
- const struct insn_offset *val2 = b;
-
- return (val1->value - val2->value);
-}
-
-static const struct ins_ops *check_ppc_insn(struct disasm_line *dl)
-{
- int raw_insn = dl->raw.raw_insn;
- int opcode = PPC_OP(raw_insn);
- int mem_insn_31 = PPC_21_30(raw_insn);
- struct insn_offset *ret;
- struct insn_offset mem_insns_31_opcode = {
- "OP_31_INSN",
- mem_insn_31
- };
- char name_insn[32];
-
- /*
- * Instructions with opcode 32 to 63 are memory
- * instructions in powerpc
- */
- if ((opcode & 0x20)) {
- /*
- * Set name in case of raw instruction to
- * opcode to be used in insn-stat
- */
- if (!strlen(dl->ins.name)) {
- sprintf(name_insn, "%d", opcode);
- dl->ins.name = strdup(name_insn);
- }
- return &load_store_ops;
- } else if (opcode == 31) {
- /* Check for memory instructions with opcode 31 */
- ret = bsearch(&mem_insns_31_opcode, ins_array, ARRAY_SIZE(ins_array), sizeof(ins_array[0]), cmp_offset);
- if (ret) {
- if (!strlen(dl->ins.name))
- dl->ins.name = strdup(ret->name);
- return &load_store_ops;
- } else {
- mem_insns_31_opcode.value = PPC_22_30(raw_insn);
- ret = bsearch(&mem_insns_31_opcode, arithmetic_ins_op_31, ARRAY_SIZE(arithmetic_ins_op_31),
- sizeof(arithmetic_ins_op_31[0]), cmp_offset);
- if (ret != NULL)
- return &arithmetic_ops;
- /* Bits 21 to 30 has value 444 for "mr" insn ie, OR X form */
- if (PPC_21_30(raw_insn) == 444)
- return &arithmetic_ops;
- }
- } else {
- mem_insns_31_opcode.value = opcode;
- ret = bsearch(&mem_insns_31_opcode, arithmetic_two_ops, ARRAY_SIZE(arithmetic_two_ops),
- sizeof(arithmetic_two_ops[0]), cmp_offset);
- if (ret != NULL)
- return &arithmetic_ops;
- }
-
- return NULL;
-}
-
-/*
- * Instruction tracking function to track register state moves.
- * Example sequence:
- * ld r10,264(r3)
- * mr r31,r3
- * <<after some sequence>
- * ld r9,312(r31)
- *
- * Previous instruction sequence shows that register state of r3
- * is moved to r31. update_insn_state_powerpc tracks these state
- * changes
- */
-#ifdef HAVE_LIBDW_SUPPORT
-static void update_insn_state_powerpc(struct type_state *state,
- struct data_loc_info *dloc, Dwarf_Die * cu_die __maybe_unused,
- struct disasm_line *dl)
-{
- struct annotated_insn_loc loc;
- struct annotated_op_loc *src = &loc.ops[INSN_OP_SOURCE];
- struct annotated_op_loc *dst = &loc.ops[INSN_OP_TARGET];
- struct type_state_reg *tsr;
- u32 insn_offset = dl->al.offset;
-
- if (annotate_get_insn_location(dloc->arch, dl, &loc) < 0)
- return;
-
- /*
- * Value 444 for bits 21:30 is for "mr"
- * instruction. "mr" is extended OR. So set the
- * source and destination reg correctly
- */
- if (PPC_21_30(dl->raw.raw_insn) == 444) {
- int src_reg = src->reg1;
-
- src->reg1 = dst->reg1;
- dst->reg1 = src_reg;
- }
-
- if (!has_reg_type(state, dst->reg1))
- return;
-
- tsr = &state->regs[dst->reg1];
-
- if (!has_reg_type(state, src->reg1) ||
- !state->regs[src->reg1].ok) {
- tsr->ok = false;
- return;
- }
-
- tsr->type = state->regs[src->reg1].type;
- tsr->kind = state->regs[src->reg1].kind;
- tsr->ok = true;
-
- pr_debug_dtp("mov [%x] reg%d -> reg%d",
- insn_offset, src->reg1, dst->reg1);
- pr_debug_type_name(&tsr->type, tsr->kind);
-}
-#endif /* HAVE_LIBDW_SUPPORT */
-
-static int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
-{
- if (!arch->initialized) {
- arch->initialized = true;
- arch->associate_instruction_ops = powerpc__associate_instruction_ops;
- arch->objdump.comment_char = '#';
- annotate_opts.show_asm_raw = true;
- arch->e_machine = EM_PPC;
- arch->e_flags = 0;
- }
-
- return 0;
-}
diff --git a/tools/perf/arch/riscv64/annotate/instructions.c b/tools/perf/arch/riscv64/annotate/instructions.c
deleted file mode 100644
index a34798864fab..000000000000
--- a/tools/perf/arch/riscv64/annotate/instructions.c
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-static
-const struct ins_ops *riscv64__associate_ins_ops(struct arch *arch, const char *name)
-{
- const struct ins_ops *ops = NULL;
-
- if (!strncmp(name, "jal", 3) ||
- !strncmp(name, "jr", 2) ||
- !strncmp(name, "call", 4))
- ops = &call_ops;
- else if (!strncmp(name, "ret", 3))
- ops = &ret_ops;
- else if (name[0] == 'j' || name[0] == 'b')
- ops = &jump_ops;
- else
- return NULL;
-
- arch__associate_ins_ops(arch, name, ops);
-
- return ops;
-}
-
-static
-int riscv64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
-{
- if (!arch->initialized) {
- arch->associate_instruction_ops = riscv64__associate_ins_ops;
- arch->initialized = true;
- arch->objdump.comment_char = '#';
- arch->e_machine = EM_RISCV;
- arch->e_flags = 0;
- }
-
- return 0;
-}
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
deleted file mode 100644
index 1b22e6276e7d..000000000000
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ /dev/null
@@ -1,178 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/compiler.h>
-
-static int s390_call__parse(const struct arch *arch, struct ins_operands *ops,
- struct map_symbol *ms,
- struct disasm_line *dl __maybe_unused)
-{
- char *endptr, *tok, *name;
- struct map *map = ms->map;
- struct addr_map_symbol target;
-
- tok = strchr(ops->raw, ',');
- if (!tok)
- return -1;
-
- ops->target.addr = strtoull(tok + 1, &endptr, 16);
-
- name = strchr(endptr, '<');
- if (name == NULL)
- return -1;
-
- name++;
-
- if (arch->objdump.skip_functions_char &&
- strchr(name, arch->objdump.skip_functions_char))
- return -1;
-
- tok = strchr(name, '>');
- if (tok == NULL)
- return -1;
-
- *tok = '\0';
- ops->target.name = strdup(name);
- *tok = '>';
-
- if (ops->target.name == NULL)
- return -1;
-
- target = (struct addr_map_symbol) {
- .ms = { .map = map__get(map), },
- .addr = map__objdump_2mem(map, ops->target.addr),
- };
-
- if (maps__find_ams(ms->maps, &target) == 0 &&
- map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
- ops->target.sym = target.ms.sym;
-
- addr_map_symbol__exit(&target);
- return 0;
-}
-
-static const struct ins_ops s390_call_ops = {
- .parse = s390_call__parse,
- .scnprintf = call__scnprintf,
-};
-
-static int s390_mov__parse(const struct arch *arch __maybe_unused,
- struct ins_operands *ops,
- struct map_symbol *ms __maybe_unused,
- struct disasm_line *dl __maybe_unused)
-{
- char *s = strchr(ops->raw, ','), *target, *endptr;
-
- if (s == NULL)
- return -1;
-
- *s = '\0';
- ops->source.raw = strdup(ops->raw);
- *s = ',';
-
- if (ops->source.raw == NULL)
- return -1;
-
- target = ++s;
- ops->target.raw = strdup(target);
- if (ops->target.raw == NULL)
- goto out_free_source;
-
- ops->target.addr = strtoull(target, &endptr, 16);
- if (endptr == target)
- goto out_free_target;
-
- s = strchr(endptr, '<');
- if (s == NULL)
- goto out_free_target;
- endptr = strchr(s + 1, '>');
- if (endptr == NULL)
- goto out_free_target;
-
- *endptr = '\0';
- ops->target.name = strdup(s + 1);
- *endptr = '>';
- if (ops->target.name == NULL)
- goto out_free_target;
-
- return 0;
-
-out_free_target:
- zfree(&ops->target.raw);
-out_free_source:
- zfree(&ops->source.raw);
- return -1;
-}
-
-
-static const struct ins_ops s390_mov_ops = {
- .parse = s390_mov__parse,
- .scnprintf = mov__scnprintf,
-};
-
-static const struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
-{
- const struct ins_ops *ops = NULL;
-
- /* catch all kind of jumps */
- if (strchr(name, 'j') ||
- !strncmp(name, "bct", 3) ||
- !strncmp(name, "br", 2))
- ops = &jump_ops;
- /* override call/returns */
- if (!strcmp(name, "bras") ||
- !strcmp(name, "brasl") ||
- !strcmp(name, "basr"))
- ops = &s390_call_ops;
- if (!strcmp(name, "br"))
- ops = &ret_ops;
- /* override load/store relative to PC */
- if (!strcmp(name, "lrl") ||
- !strcmp(name, "lgrl") ||
- !strcmp(name, "lgfrl") ||
- !strcmp(name, "llgfrl") ||
- !strcmp(name, "strl") ||
- !strcmp(name, "stgrl"))
- ops = &s390_mov_ops;
-
- if (ops)
- arch__associate_ins_ops(arch, name, ops);
- return ops;
-}
-
-static int s390__cpuid_parse(struct arch *arch, char *cpuid)
-{
- unsigned int family;
- char model[16], model_c[16], cpumf_v[16], cpumf_a[16];
- int ret;
-
- /*
- * cpuid string format:
- * "IBM,family,model-capacity,model[,cpum_cf-version,cpum_cf-authorization]"
- */
- ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%s", &family, model_c,
- model, cpumf_v, cpumf_a);
- if (ret >= 2) {
- arch->family = family;
- arch->model = 0;
- return 0;
- }
-
- return -1;
-}
-
-static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
-{
- int err = 0;
-
- if (!arch->initialized) {
- arch->initialized = true;
- arch->associate_instruction_ops = s390__associate_ins_ops;
- if (cpuid) {
- if (s390__cpuid_parse(arch, cpuid))
- err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
- }
- arch->e_machine = EM_S390;
- arch->e_flags = 0;
- }
-
- return err;
-}
diff --git a/tools/perf/arch/sparc/annotate/instructions.c b/tools/perf/arch/sparc/annotate/instructions.c
deleted file mode 100644
index a08d8734c883..000000000000
--- a/tools/perf/arch/sparc/annotate/instructions.c
+++ /dev/null
@@ -1,171 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-static int is_branch_cond(const char *cond)
-{
- if (cond[0] == '\0')
- return 1;
-
- if (cond[0] == 'a' && cond[1] == '\0')
- return 1;
-
- if (cond[0] == 'c' &&
- (cond[1] == 'c' || cond[1] == 's') &&
- cond[2] == '\0')
- return 1;
-
- if (cond[0] == 'e' &&
- (cond[1] == '\0' ||
- (cond[1] == 'q' && cond[2] == '\0')))
- return 1;
-
- if (cond[0] == 'g' &&
- (cond[1] == '\0' ||
- (cond[1] == 't' && cond[2] == '\0') ||
- (cond[1] == 'e' && cond[2] == '\0') ||
- (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
- return 1;
-
- if (cond[0] == 'l' &&
- (cond[1] == '\0' ||
- (cond[1] == 't' && cond[2] == '\0') ||
- (cond[1] == 'u' && cond[2] == '\0') ||
- (cond[1] == 'e' && cond[2] == '\0') ||
- (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
- return 1;
-
- if (cond[0] == 'n' &&
- (cond[1] == '\0' ||
- (cond[1] == 'e' && cond[2] == '\0') ||
- (cond[1] == 'z' && cond[2] == '\0') ||
- (cond[1] == 'e' && cond[2] == 'g' && cond[3] == '\0')))
- return 1;
-
- if (cond[0] == 'b' &&
- cond[1] == 'p' &&
- cond[2] == 'o' &&
- cond[3] == 's' &&
- cond[4] == '\0')
- return 1;
-
- if (cond[0] == 'v' &&
- (cond[1] == 'c' || cond[1] == 's') &&
- cond[2] == '\0')
- return 1;
-
- if (cond[0] == 'b' &&
- cond[1] == 'z' &&
- cond[2] == '\0')
- return 1;
-
- return 0;
-}
-
-static int is_branch_reg_cond(const char *cond)
-{
- if ((cond[0] == 'n' || cond[0] == 'l') &&
- cond[1] == 'z' &&
- cond[2] == '\0')
- return 1;
-
- if (cond[0] == 'z' &&
- cond[1] == '\0')
- return 1;
-
- if ((cond[0] == 'g' || cond[0] == 'l') &&
- cond[1] == 'e' &&
- cond[2] == 'z' &&
- cond[3] == '\0')
- return 1;
-
- if (cond[0] == 'g' &&
- cond[1] == 'z' &&
- cond[2] == '\0')
- return 1;
-
- return 0;
-}
-
-static int is_branch_float_cond(const char *cond)
-{
- if (cond[0] == '\0')
- return 1;
-
- if ((cond[0] == 'a' || cond[0] == 'e' ||
- cond[0] == 'z' || cond[0] == 'g' ||
- cond[0] == 'l' || cond[0] == 'n' ||
- cond[0] == 'o' || cond[0] == 'u') &&
- cond[1] == '\0')
- return 1;
-
- if (((cond[0] == 'g' && cond[1] == 'e') ||
- (cond[0] == 'l' && (cond[1] == 'e' ||
- cond[1] == 'g')) ||
- (cond[0] == 'n' && (cond[1] == 'e' ||
- cond[1] == 'z')) ||
- (cond[0] == 'u' && (cond[1] == 'e' ||
- cond[1] == 'g' ||
- cond[1] == 'l'))) &&
- cond[2] == '\0')
- return 1;
-
- if (cond[0] == 'u' &&
- (cond[1] == 'g' || cond[1] == 'l') &&
- cond[2] == 'e' &&
- cond[3] == '\0')
- return 1;
-
- return 0;
-}
-
-static const struct ins_ops *sparc__associate_instruction_ops(struct arch *arch, const char *name)
-{
- const struct ins_ops *ops = NULL;
-
- if (!strcmp(name, "call") ||
- !strcmp(name, "jmp") ||
- !strcmp(name, "jmpl")) {
- ops = &call_ops;
- } else if (!strcmp(name, "ret") ||
- !strcmp(name, "retl") ||
- !strcmp(name, "return")) {
- ops = &ret_ops;
- } else if (!strcmp(name, "mov")) {
- ops = &mov_ops;
- } else {
- if (name[0] == 'c' &&
- (name[1] == 'w' || name[1] == 'x'))
- name += 2;
-
- if (name[0] == 'b') {
- const char *cond = name + 1;
-
- if (cond[0] == 'r') {
- if (is_branch_reg_cond(cond + 1))
- ops = &jump_ops;
- } else if (is_branch_cond(cond)) {
- ops = &jump_ops;
- }
- } else if (name[0] == 'f' && name[1] == 'b') {
- if (is_branch_float_cond(name + 2))
- ops = &jump_ops;
- }
- }
-
- if (ops)
- arch__associate_ins_ops(arch, name, ops);
-
- return ops;
-}
-
-static int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
-{
- if (!arch->initialized) {
- arch->initialized = true;
- arch->associate_instruction_ops = sparc__associate_instruction_ops;
- arch->objdump.comment_char = '#';
- arch->e_machine = EM_SPARC;
- arch->e_flags = 0;
- }
-
- return 0;
-}
diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c
deleted file mode 100644
index ffca3029388b..000000000000
--- a/tools/perf/arch/x86/annotate/instructions.c
+++ /dev/null
@@ -1,797 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * x86 instruction nmemonic table to parse disasm lines for annotate.
- * This table is searched twice - one for exact match and another for
- * match without a size suffix (b, w, l, q) in case of AT&T syntax.
- *
- * So this table should not have entries with the suffix unless it's
- * a complete different instruction than ones without the suffix.
- */
-static const struct ins x86__instructions[] = {
- { .name = "adc", .ops = &mov_ops, },
- { .name = "add", .ops = &mov_ops, },
- { .name = "addsd", .ops = &mov_ops, },
- { .name = "and", .ops = &mov_ops, },
- { .name = "andpd", .ops = &mov_ops, },
- { .name = "andps", .ops = &mov_ops, },
- { .name = "bsr", .ops = &mov_ops, },
- { .name = "bt", .ops = &mov_ops, },
- { .name = "btr", .ops = &mov_ops, },
- { .name = "bts", .ops = &mov_ops, },
- { .name = "call", .ops = &call_ops, },
- { .name = "cmovae", .ops = &mov_ops, },
- { .name = "cmovbe", .ops = &mov_ops, },
- { .name = "cmove", .ops = &mov_ops, },
- { .name = "cmp", .ops = &mov_ops, },
- { .name = "cmpxch", .ops = &mov_ops, },
- { .name = "cmpxchg", .ops = &mov_ops, },
- { .name = "cs", .ops = &mov_ops, },
- { .name = "dec", .ops = &dec_ops, },
- { .name = "divsd", .ops = &mov_ops, },
- { .name = "divss", .ops = &mov_ops, },
- { .name = "gs", .ops = &mov_ops, },
- { .name = "imul", .ops = &mov_ops, },
- { .name = "inc", .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 = "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 = "movapd", .ops = &mov_ops, },
- { .name = "movaps", .ops = &mov_ops, },
- { .name = "movdqa", .ops = &mov_ops, },
- { .name = "movdqu", .ops = &mov_ops, },
- { .name = "movsb", .ops = &mov_ops, },
- { .name = "movsd", .ops = &mov_ops, },
- { .name = "movsl", .ops = &mov_ops, },
- { .name = "movss", .ops = &mov_ops, },
- { .name = "movsw", .ops = &mov_ops, },
- { .name = "movupd", .ops = &mov_ops, },
- { .name = "movups", .ops = &mov_ops, },
- { .name = "movzb", .ops = &mov_ops, },
- { .name = "movzl", .ops = &mov_ops, },
- { .name = "movzw", .ops = &mov_ops, },
- { .name = "mulsd", .ops = &mov_ops, },
- { .name = "mulss", .ops = &mov_ops, },
- { .name = "nop", .ops = &nop_ops, },
- { .name = "or", .ops = &mov_ops, },
- { .name = "orps", .ops = &mov_ops, },
- { .name = "paddq", .ops = &mov_ops, },
- { .name = "pand", .ops = &mov_ops, },
- { .name = "pcmpeqb", .ops = &mov_ops, },
- { .name = "por", .ops = &mov_ops, },
- { .name = "rcl", .ops = &mov_ops, },
- { .name = "ret", .ops = &ret_ops, },
- { .name = "sbb", .ops = &mov_ops, },
- { .name = "sete", .ops = &mov_ops, },
- { .name = "sub", .ops = &mov_ops, },
- { .name = "subsd", .ops = &mov_ops, },
- { .name = "test", .ops = &mov_ops, },
- { .name = "tzcnt", .ops = &mov_ops, },
- { .name = "ucomisd", .ops = &mov_ops, },
- { .name = "ucomiss", .ops = &mov_ops, },
- { .name = "vaddsd", .ops = &mov_ops, },
- { .name = "vandpd", .ops = &mov_ops, },
- { .name = "vmovdqa", .ops = &mov_ops, },
- { .name = "vmovq", .ops = &mov_ops, },
- { .name = "vmovsd", .ops = &mov_ops, },
- { .name = "vmulsd", .ops = &mov_ops, },
- { .name = "vorpd", .ops = &mov_ops, },
- { .name = "vsubsd", .ops = &mov_ops, },
- { .name = "vucomisd", .ops = &mov_ops, },
- { .name = "xadd", .ops = &mov_ops, },
- { .name = "xbegin", .ops = &jump_ops, },
- { .name = "xchg", .ops = &mov_ops, },
- { .name = "xor", .ops = &mov_ops, },
- { .name = "xorpd", .ops = &mov_ops, },
- { .name = "xorps", .ops = &mov_ops, },
-};
-
-static bool amd__ins_is_fused(const struct arch *arch, const char *ins1,
- const char *ins2)
-{
- if (strstr(ins2, "jmp"))
- return false;
-
- /* Family >= 15h supports cmp/test + branch fusion */
- if (arch->family >= 0x15 && (strstarts(ins1, "test") ||
- (strstarts(ins1, "cmp") && !strstr(ins1, "xchg")))) {
- return true;
- }
-
- /* Family >= 19h supports some ALU + branch fusion */
- if (arch->family >= 0x19 && (strstarts(ins1, "add") ||
- strstarts(ins1, "sub") || strstarts(ins1, "and") ||
- strstarts(ins1, "inc") || strstarts(ins1, "dec") ||
- strstarts(ins1, "or") || strstarts(ins1, "xor"))) {
- return true;
- }
-
- return false;
-}
-
-static bool intel__ins_is_fused(const struct arch *arch, const char *ins1,
- const char *ins2)
-{
- if (arch->family != 6 || arch->model < 0x1e || strstr(ins2, "jmp"))
- return false;
-
- if (arch->model == 0x1e) {
- /* Nehalem */
- if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
- strstr(ins1, "test")) {
- return true;
- }
- } else {
- /* Newer platform */
- if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
- strstr(ins1, "test") ||
- strstr(ins1, "add") ||
- strstr(ins1, "sub") ||
- strstr(ins1, "and") ||
- strstr(ins1, "inc") ||
- strstr(ins1, "dec")) {
- return true;
- }
- }
-
- return false;
-}
-
-static int x86__cpuid_parse(struct arch *arch, char *cpuid)
-{
- unsigned int family, model, stepping;
- int ret;
-
- /*
- * cpuid = "GenuineIntel,family,model,stepping"
- */
- ret = sscanf(cpuid, "%*[^,],%u,%u,%u", &family, &model, &stepping);
- if (ret == 3) {
- arch->family = family;
- arch->model = model;
- arch->ins_is_fused = strstarts(cpuid, "AuthenticAMD") ?
- amd__ins_is_fused :
- intel__ins_is_fused;
- return 0;
- }
-
- return -1;
-}
-
-static int x86__annotate_init(struct arch *arch, char *cpuid)
-{
- int err = 0;
-
- if (arch->initialized)
- return 0;
-
- if (cpuid) {
- if (x86__cpuid_parse(arch, cpuid))
- err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
- }
-
-#ifndef NDEBUG
- {
- static bool sorted_check;
-
- if (!sorted_check) {
- for (size_t i = 0; i < arch->nr_instructions - 1; i++) {
- assert(strcmp(arch->instructions[i].name,
- arch->instructions[i + 1].name) <= 0);
- }
- sorted_check = true;
- }
- }
-#endif
- arch->e_machine = EM_X86_64;
- arch->e_flags = 0;
- arch->initialized = true;
- return err;
-}
-
-#ifdef HAVE_LIBDW_SUPPORT
-static void update_insn_state_x86(struct type_state *state,
- struct data_loc_info *dloc, Dwarf_Die *cu_die,
- struct disasm_line *dl)
-{
- struct annotated_insn_loc loc;
- struct annotated_op_loc *src = &loc.ops[INSN_OP_SOURCE];
- struct annotated_op_loc *dst = &loc.ops[INSN_OP_TARGET];
- struct type_state_reg *tsr;
- Dwarf_Die type_die;
- u32 insn_offset = dl->al.offset;
- int fbreg = dloc->fbreg;
- int fboff = 0;
-
- if (annotate_get_insn_location(dloc->arch, dl, &loc) < 0)
- return;
-
- if (ins__is_call(&dl->ins)) {
- struct symbol *func = dl->ops.target.sym;
-
- if (func == NULL)
- return;
-
- /* __fentry__ will preserve all registers */
- if (!strcmp(func->name, "__fentry__"))
- return;
-
- pr_debug_dtp("call [%x] %s\n", insn_offset, func->name);
-
- /* Otherwise invalidate caller-saved registers after call */
- for (unsigned i = 0; i < ARRAY_SIZE(state->regs); i++) {
- if (state->regs[i].caller_saved)
- state->regs[i].ok = false;
- }
-
- /* Update register with the return type (if any) */
- if (die_find_func_rettype(cu_die, func->name, &type_die)) {
- tsr = &state->regs[state->ret_reg];
- tsr->type = type_die;
- tsr->kind = TSR_KIND_TYPE;
- tsr->offset = 0;
- tsr->ok = true;
-
- pr_debug_dtp("call [%x] return -> reg%d",
- insn_offset, state->ret_reg);
- pr_debug_type_name(&type_die, tsr->kind);
- }
- return;
- }
-
- if (!strncmp(dl->ins.name, "add", 3)) {
- u64 imm_value = -1ULL;
- int offset;
- const char *var_name = NULL;
- struct map_symbol *ms = dloc->ms;
- u64 ip = ms->sym->start + dl->al.offset;
-
- if (!has_reg_type(state, dst->reg1))
- return;
-
- tsr = &state->regs[dst->reg1];
- tsr->copied_from = -1;
-
- if (src->imm)
- imm_value = src->offset;
- else if (has_reg_type(state, src->reg1) &&
- state->regs[src->reg1].kind == TSR_KIND_CONST)
- imm_value = state->regs[src->reg1].imm_value;
- else if (src->reg1 == DWARF_REG_PC) {
- u64 var_addr = annotate_calc_pcrel(dloc->ms, ip,
- src->offset, dl);
-
- if (get_global_var_info(dloc, var_addr,
- &var_name, &offset) &&
- !strcmp(var_name, "this_cpu_off") &&
- tsr->kind == TSR_KIND_CONST) {
- tsr->kind = TSR_KIND_PERCPU_BASE;
- tsr->offset = 0;
- tsr->ok = true;
- imm_value = tsr->imm_value;
- }
- }
- else
- return;
-
- /* Ignore add to non-pointer or non-const types */
- if (tsr->kind == TSR_KIND_POINTER ||
- (dwarf_tag(&tsr->type) == DW_TAG_pointer_type &&
- src->reg1 != DWARF_REG_PC && tsr->kind == TSR_KIND_TYPE && !dst->mem_ref)) {
- tsr->offset += imm_value;
- pr_debug_dtp("add [%x] offset %#"PRIx64" to reg%d",
- insn_offset, imm_value, dst->reg1);
- pr_debug_type_name(&tsr->type, tsr->kind);
- }
-
- if (tsr->kind == TSR_KIND_CONST)
- tsr->imm_value += imm_value;
-
- if (tsr->kind != TSR_KIND_PERCPU_BASE)
- return;
-
- if (get_global_var_type(cu_die, dloc, ip, imm_value, &offset,
- &type_die) && offset == 0) {
- /*
- * This is not a pointer type, but it should be treated
- * as a pointer.
- */
- tsr->type = type_die;
- tsr->kind = TSR_KIND_PERCPU_POINTER;
- tsr->offset = 0;
- tsr->ok = true;
-
- pr_debug_dtp("add [%x] percpu %#"PRIx64" -> reg%d",
- insn_offset, imm_value, dst->reg1);
- pr_debug_type_name(&tsr->type, tsr->kind);
- }
- return;
- }
-
- if (!strncmp(dl->ins.name, "sub", 3)) {
- u64 imm_value = -1ULL;
-
- if (!has_reg_type(state, dst->reg1))
- return;
-
- tsr = &state->regs[dst->reg1];
- tsr->copied_from = -1;
-
- if (src->imm)
- imm_value = src->offset;
- else if (has_reg_type(state, src->reg1) &&
- state->regs[src->reg1].kind == TSR_KIND_CONST)
- imm_value = state->regs[src->reg1].imm_value;
-
- if (tsr->kind == TSR_KIND_POINTER ||
- (dwarf_tag(&tsr->type) == DW_TAG_pointer_type &&
- src->reg1 != DWARF_REG_PC && tsr->kind == TSR_KIND_TYPE && !dst->mem_ref)) {
- tsr->offset -= imm_value;
- pr_debug_dtp("sub [%x] offset %#"PRIx64" to reg%d",
- insn_offset, imm_value, dst->reg1);
- pr_debug_type_name(&tsr->type, tsr->kind);
- }
-
- if (tsr->kind == TSR_KIND_CONST)
- tsr->imm_value -= imm_value;
-
- return;
- }
-
- if (!strncmp(dl->ins.name, "lea", 3)) {
- int sreg = src->reg1;
- struct type_state_reg src_tsr;
-
- if (!has_reg_type(state, sreg) ||
- !has_reg_type(state, dst->reg1) ||
- !src->mem_ref)
- return;
-
- src_tsr = state->regs[sreg];
- tsr = &state->regs[dst->reg1];
-
- tsr->copied_from = -1;
- tsr->ok = false;
-
- /* Case 1: Based on stack pointer or frame pointer */
- if (sreg == fbreg || sreg == state->stack_reg) {
- struct type_state_stack *stack;
- int offset = src->offset - fboff;
-
- stack = find_stack_state(state, offset);
- if (!stack)
- return;
-
- tsr->type = stack->type;
- tsr->kind = TSR_KIND_POINTER;
- tsr->offset = offset - stack->offset;
- tsr->ok = true;
-
- if (sreg == fbreg) {
- pr_debug_dtp("lea [%x] address of -%#x(stack) -> reg%d",
- insn_offset, -src->offset, dst->reg1);
- } else {
- pr_debug_dtp("lea [%x] address of %#x(reg%d) -> reg%d",
- insn_offset, src->offset, sreg, dst->reg1);
- }
-
- pr_debug_type_name(&tsr->type, tsr->kind);
- }
- /* Case 2: Based on a register holding a typed pointer */
- else if (src_tsr.ok && (src_tsr.kind == TSR_KIND_POINTER ||
- (dwarf_tag(&src_tsr.type) == DW_TAG_pointer_type &&
- src_tsr.kind == TSR_KIND_TYPE))) {
-
- if (src_tsr.kind == TSR_KIND_TYPE &&
- __die_get_real_type(&state->regs[sreg].type, &type_die) == NULL)
- return;
-
- if (src_tsr.kind == TSR_KIND_POINTER)
- type_die = state->regs[sreg].type;
-
- /* Check if the target type has a member at the new offset */
- if (die_get_member_type(&type_die,
- src->offset + src_tsr.offset, &type_die) == NULL)
- return;
-
- tsr->type = src_tsr.type;
- tsr->kind = src_tsr.kind;
- tsr->offset = src->offset + src_tsr.offset;
- tsr->ok = true;
-
- pr_debug_dtp("lea [%x] address of %s%#x(reg%d) -> reg%d",
- insn_offset, src->offset < 0 ? "-" : "",
- abs(src->offset), sreg, dst->reg1);
-
- pr_debug_type_name(&tsr->type, tsr->kind);
- }
- return;
- }
-
- /* Invalidate register states for other ops which may change pointers */
- if (has_reg_type(state, dst->reg1) && !dst->mem_ref &&
- dwarf_tag(&state->regs[dst->reg1].type) == DW_TAG_pointer_type) {
- if (!strncmp(dl->ins.name, "imul", 4) || !strncmp(dl->ins.name, "mul", 3) ||
- !strncmp(dl->ins.name, "idiv", 4) || !strncmp(dl->ins.name, "div", 3) ||
- !strncmp(dl->ins.name, "shl", 3) || !strncmp(dl->ins.name, "shr", 3) ||
- !strncmp(dl->ins.name, "sar", 3) || !strncmp(dl->ins.name, "and", 3) ||
- !strncmp(dl->ins.name, "or", 2) || !strncmp(dl->ins.name, "neg", 3) ||
- !strncmp(dl->ins.name, "inc", 3) || !strncmp(dl->ins.name, "dec", 3)) {
- pr_debug_dtp("%s [%x] invalidate reg%d\n",
- dl->ins.name, insn_offset, dst->reg1);
- state->regs[dst->reg1].ok = false;
- state->regs[dst->reg1].copied_from = -1;
- return;
- }
-
- if (!strncmp(dl->ins.name, "xor", 3) && dst->reg1 == src->reg1) {
- /* xor reg, reg clears the register */
- pr_debug_dtp("xor [%x] clear reg%d\n",
- insn_offset, dst->reg1);
-
- state->regs[dst->reg1].kind = TSR_KIND_CONST;
- state->regs[dst->reg1].imm_value = 0;
- state->regs[dst->reg1].ok = true;
- state->regs[dst->reg1].copied_from = -1;
- return;
- }
- }
-
- if (strncmp(dl->ins.name, "mov", 3))
- return;
-
- if (dloc->fb_cfa) {
- u64 ip = dloc->ms->sym->start + dl->al.offset;
- u64 pc = map__rip_2objdump(dloc->ms->map, ip);
-
- if (die_get_cfa(dloc->di->dbg, pc, &fbreg, &fboff) < 0)
- fbreg = -1;
- }
-
- /* Case 1. register to register or segment:offset to register transfers */
- if (!src->mem_ref && !dst->mem_ref) {
- if (!has_reg_type(state, dst->reg1))
- return;
-
- tsr = &state->regs[dst->reg1];
- tsr->copied_from = -1;
-
- if (dso__kernel(map__dso(dloc->ms->map)) &&
- src->segment == INSN_SEG_X86_GS && src->imm) {
- u64 ip = dloc->ms->sym->start + dl->al.offset;
- u64 var_addr;
- int offset;
-
- /*
- * In kernel, %gs points to a per-cpu region for the
- * current CPU. Access with a constant offset should
- * be treated as a global variable access.
- */
- var_addr = src->offset;
-
- if (var_addr == 40) {
- tsr->kind = TSR_KIND_CANARY;
- tsr->offset = 0;
- tsr->ok = true;
-
- pr_debug_dtp("mov [%x] stack canary -> reg%d\n",
- insn_offset, dst->reg1);
- return;
- }
-
- if (!get_global_var_type(cu_die, dloc, ip, var_addr,
- &offset, &type_die) ||
- !die_get_member_type(&type_die, offset, &type_die)) {
- tsr->ok = false;
- return;
- }
-
- tsr->type = type_die;
- tsr->kind = TSR_KIND_TYPE;
- tsr->offset = 0;
- tsr->ok = true;
-
- pr_debug_dtp("mov [%x] this-cpu addr=%#"PRIx64" -> reg%d",
- insn_offset, var_addr, dst->reg1);
- pr_debug_type_name(&tsr->type, tsr->kind);
- return;
- }
-
- if (src->imm) {
- tsr->kind = TSR_KIND_CONST;
- tsr->imm_value = src->offset;
- tsr->offset = 0;
- tsr->ok = true;
-
- pr_debug_dtp("mov [%x] imm=%#x -> reg%d\n",
- insn_offset, tsr->imm_value, dst->reg1);
- return;
- }
-
- if (!has_reg_type(state, src->reg1) ||
- !state->regs[src->reg1].ok) {
- tsr->ok = false;
- return;
- }
-
- tsr->type = state->regs[src->reg1].type;
- tsr->kind = state->regs[src->reg1].kind;
- tsr->imm_value = state->regs[src->reg1].imm_value;
- tsr->offset = state->regs[src->reg1].offset;
- tsr->ok = true;
-
- /* To copy back the variable type later (hopefully) */
- if (tsr->kind == TSR_KIND_TYPE || tsr->kind == TSR_KIND_POINTER)
- tsr->copied_from = src->reg1;
-
- pr_debug_dtp("mov [%x] reg%d -> reg%d",
- insn_offset, src->reg1, dst->reg1);
- pr_debug_type_name(&tsr->type, tsr->kind);
- }
- /* Case 2. memory to register transers */
- if (src->mem_ref && !dst->mem_ref) {
- int sreg = src->reg1;
-
- if (!has_reg_type(state, dst->reg1))
- return;
-
- tsr = &state->regs[dst->reg1];
- tsr->copied_from = -1;
-
-retry:
- /* Check stack variables with offset */
- if (sreg == fbreg || sreg == state->stack_reg) {
- struct type_state_stack *stack;
- int offset = src->offset - fboff;
-
- stack = find_stack_state(state, offset);
- if (stack == NULL) {
- tsr->ok = false;
- return;
- } else if (!stack->compound) {
- tsr->type = stack->type;
- tsr->kind = stack->kind;
- tsr->offset = stack->ptr_offset;
- tsr->ok = true;
- } else if (die_get_member_type(&stack->type,
- offset - stack->offset,
- &type_die)) {
- tsr->type = type_die;
- tsr->kind = TSR_KIND_TYPE;
- tsr->offset = 0;
- tsr->ok = true;
- } else {
- tsr->ok = false;
- return;
- }
-
- if (sreg == fbreg) {
- pr_debug_dtp("mov [%x] -%#x(stack) -> reg%d",
- insn_offset, -offset, dst->reg1);
- } else {
- pr_debug_dtp("mov [%x] %#x(reg%d) -> reg%d",
- insn_offset, offset, sreg, dst->reg1);
- }
- pr_debug_type_name(&tsr->type, tsr->kind);
- }
- /* And then dereference the pointer if it has one */
- else if (has_reg_type(state, sreg) && state->regs[sreg].ok &&
- state->regs[sreg].kind == TSR_KIND_TYPE &&
- die_deref_ptr_type(&state->regs[sreg].type,
- src->offset + state->regs[sreg].offset, &type_die)) {
- tsr->type = type_die;
- tsr->kind = TSR_KIND_TYPE;
- tsr->offset = 0;
- tsr->ok = true;
-
- pr_debug_dtp("mov [%x] %#x(reg%d) -> reg%d",
- insn_offset, src->offset, sreg, dst->reg1);
- pr_debug_type_name(&tsr->type, tsr->kind);
- }
- /* Handle dereference of TSR_KIND_POINTER registers */
- else if (has_reg_type(state, sreg) && state->regs[sreg].ok &&
- state->regs[sreg].kind == TSR_KIND_POINTER &&
- die_get_member_type(&state->regs[sreg].type,
- src->offset + state->regs[sreg].offset, &type_die)) {
- tsr->type = state->regs[sreg].type;
- tsr->kind = TSR_KIND_TYPE;
- tsr->offset = src->offset + state->regs[sreg].offset;
- tsr->ok = true;
-
- pr_debug_dtp("mov [%x] addr %#x(reg%d) -> reg%d",
- insn_offset, src->offset, sreg, dst->reg1);
- pr_debug_type_name(&tsr->type, tsr->kind);
- }
- /* Or check if it's a global variable */
- else if (sreg == DWARF_REG_PC) {
- struct map_symbol *ms = dloc->ms;
- u64 ip = ms->sym->start + dl->al.offset;
- u64 addr;
- int offset;
-
- addr = annotate_calc_pcrel(ms, ip, src->offset, dl);
-
- if (!get_global_var_type(cu_die, dloc, ip, addr, &offset,
- &type_die) ||
- !die_get_member_type(&type_die, offset, &type_die)) {
- tsr->ok = false;
- return;
- }
-
- tsr->type = type_die;
- tsr->kind = TSR_KIND_TYPE;
- tsr->offset = 0;
- tsr->ok = true;
-
- pr_debug_dtp("mov [%x] global addr=%"PRIx64" -> reg%d",
- insn_offset, addr, dst->reg1);
- pr_debug_type_name(&type_die, tsr->kind);
- }
- /* And check percpu access with base register */
- else if (has_reg_type(state, sreg) &&
- state->regs[sreg].kind == TSR_KIND_PERCPU_BASE) {
- u64 ip = dloc->ms->sym->start + dl->al.offset;
- u64 var_addr = src->offset;
- int offset;
-
- if (src->multi_regs) {
- int reg2 = (sreg == src->reg1) ? src->reg2 : src->reg1;
-
- if (has_reg_type(state, reg2) && state->regs[reg2].ok &&
- state->regs[reg2].kind == TSR_KIND_CONST)
- var_addr += state->regs[reg2].imm_value;
- }
-
- /*
- * In kernel, %gs points to a per-cpu region for the
- * current CPU. Access with a constant offset should
- * be treated as a global variable access.
- */
- if (get_global_var_type(cu_die, dloc, ip, var_addr,
- &offset, &type_die) &&
- die_get_member_type(&type_die, offset, &type_die)) {
- tsr->type = type_die;
- tsr->kind = TSR_KIND_TYPE;
- tsr->offset = 0;
- tsr->ok = true;
-
- if (src->multi_regs) {
- pr_debug_dtp("mov [%x] percpu %#x(reg%d,reg%d) -> reg%d",
- insn_offset, src->offset, src->reg1,
- src->reg2, dst->reg1);
- } else {
- pr_debug_dtp("mov [%x] percpu %#x(reg%d) -> reg%d",
- insn_offset, src->offset, sreg, dst->reg1);
- }
- pr_debug_type_name(&tsr->type, tsr->kind);
- } else {
- tsr->ok = false;
- }
- }
- /* And then dereference the calculated pointer if it has one */
- else if (has_reg_type(state, sreg) && state->regs[sreg].ok &&
- state->regs[sreg].kind == TSR_KIND_PERCPU_POINTER &&
- die_get_member_type(&state->regs[sreg].type,
- src->offset, &type_die)) {
- tsr->type = type_die;
- tsr->kind = TSR_KIND_TYPE;
- tsr->offset = 0;
- tsr->ok = true;
-
- pr_debug_dtp("mov [%x] pointer %#x(reg%d) -> reg%d",
- insn_offset, src->offset, sreg, dst->reg1);
- pr_debug_type_name(&tsr->type, tsr->kind);
- }
- /* Or try another register if any */
- else if (src->multi_regs && sreg == src->reg1 &&
- src->reg1 != src->reg2) {
- sreg = src->reg2;
- goto retry;
- }
- else {
- int offset;
- const char *var_name = NULL;
-
- /* it might be per-cpu variable (in kernel) access */
- if (src->offset < 0) {
- if (get_global_var_info(dloc, (s64)src->offset,
- &var_name, &offset) &&
- !strcmp(var_name, "__per_cpu_offset")) {
- tsr->kind = TSR_KIND_PERCPU_BASE;
- tsr->offset = 0;
- tsr->ok = true;
-
- pr_debug_dtp("mov [%x] percpu base reg%d\n",
- insn_offset, dst->reg1);
- return;
- }
- }
-
- tsr->ok = false;
- }
- }
- /* Case 3. register to memory transfers */
- if (!src->mem_ref && dst->mem_ref) {
- if (!has_reg_type(state, src->reg1) ||
- !state->regs[src->reg1].ok)
- return;
-
- /* Check stack variables with offset */
- if (dst->reg1 == fbreg || dst->reg1 == state->stack_reg) {
- struct type_state_stack *stack;
- int offset = dst->offset - fboff;
-
- tsr = &state->regs[src->reg1];
-
- stack = find_stack_state(state, offset);
- if (stack) {
- /*
- * The source register is likely to hold a type
- * of member if it's a compound type. Do not
- * update the stack variable type since we can
- * get the member type later by using the
- * die_get_member_type().
- */
- if (!stack->compound)
- set_stack_state(stack, offset, tsr->kind,
- &tsr->type, tsr->offset);
- } else {
- findnew_stack_state(state, offset, tsr->kind,
- &tsr->type, tsr->offset);
- }
-
- if (dst->reg1 == fbreg) {
- pr_debug_dtp("mov [%x] reg%d -> -%#x(stack)",
- insn_offset, src->reg1, -offset);
- } else {
- pr_debug_dtp("mov [%x] reg%d -> %#x(reg%d)",
- insn_offset, src->reg1, offset, dst->reg1);
- }
- if (tsr->offset != 0) {
- pr_debug_dtp(" reg%d offset %#x ->",
- src->reg1, tsr->offset);
- }
-
- pr_debug_type_name(&tsr->type, tsr->kind);
- }
- /*
- * Ignore other transfers since it'd set a value in a struct
- * and won't change the type.
- */
- }
- /* Case 4. memory to memory transfers (not handled for now) */
-}
-#endif