linux/tools/perf/arch/x86/annotate/instructions.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2static struct ins x86__instructions[] = {
   3        { .name = "adc",        .ops = &mov_ops,  },
   4        { .name = "adcb",       .ops = &mov_ops,  },
   5        { .name = "adcl",       .ops = &mov_ops,  },
   6        { .name = "add",        .ops = &mov_ops,  },
   7        { .name = "addl",       .ops = &mov_ops,  },
   8        { .name = "addq",       .ops = &mov_ops,  },
   9        { .name = "addsd",      .ops = &mov_ops,  },
  10        { .name = "addw",       .ops = &mov_ops,  },
  11        { .name = "and",        .ops = &mov_ops,  },
  12        { .name = "andb",       .ops = &mov_ops,  },
  13        { .name = "andl",       .ops = &mov_ops,  },
  14        { .name = "andpd",      .ops = &mov_ops,  },
  15        { .name = "andps",      .ops = &mov_ops,  },
  16        { .name = "andq",       .ops = &mov_ops,  },
  17        { .name = "andw",       .ops = &mov_ops,  },
  18        { .name = "bsr",        .ops = &mov_ops,  },
  19        { .name = "bt",         .ops = &mov_ops,  },
  20        { .name = "btr",        .ops = &mov_ops,  },
  21        { .name = "bts",        .ops = &mov_ops,  },
  22        { .name = "btsq",       .ops = &mov_ops,  },
  23        { .name = "call",       .ops = &call_ops, },
  24        { .name = "callq",      .ops = &call_ops, },
  25        { .name = "cmovbe",     .ops = &mov_ops,  },
  26        { .name = "cmove",      .ops = &mov_ops,  },
  27        { .name = "cmovae",     .ops = &mov_ops,  },
  28        { .name = "cmp",        .ops = &mov_ops,  },
  29        { .name = "cmpb",       .ops = &mov_ops,  },
  30        { .name = "cmpl",       .ops = &mov_ops,  },
  31        { .name = "cmpq",       .ops = &mov_ops,  },
  32        { .name = "cmpw",       .ops = &mov_ops,  },
  33        { .name = "cmpxch",     .ops = &mov_ops,  },
  34        { .name = "cmpxchg",    .ops = &mov_ops,  },
  35        { .name = "cs",         .ops = &mov_ops,  },
  36        { .name = "dec",        .ops = &dec_ops,  },
  37        { .name = "decl",       .ops = &dec_ops,  },
  38        { .name = "divsd",      .ops = &mov_ops,  },
  39        { .name = "divss",      .ops = &mov_ops,  },
  40        { .name = "gs",         .ops = &mov_ops,  },
  41        { .name = "imul",       .ops = &mov_ops,  },
  42        { .name = "inc",        .ops = &dec_ops,  },
  43        { .name = "incl",       .ops = &dec_ops,  },
  44        { .name = "ja",         .ops = &jump_ops, },
  45        { .name = "jae",        .ops = &jump_ops, },
  46        { .name = "jb",         .ops = &jump_ops, },
  47        { .name = "jbe",        .ops = &jump_ops, },
  48        { .name = "jc",         .ops = &jump_ops, },
  49        { .name = "jcxz",       .ops = &jump_ops, },
  50        { .name = "je",         .ops = &jump_ops, },
  51        { .name = "jecxz",      .ops = &jump_ops, },
  52        { .name = "jg",         .ops = &jump_ops, },
  53        { .name = "jge",        .ops = &jump_ops, },
  54        { .name = "jl",         .ops = &jump_ops, },
  55        { .name = "jle",        .ops = &jump_ops, },
  56        { .name = "jmp",        .ops = &jump_ops, },
  57        { .name = "jmpq",       .ops = &jump_ops, },
  58        { .name = "jna",        .ops = &jump_ops, },
  59        { .name = "jnae",       .ops = &jump_ops, },
  60        { .name = "jnb",        .ops = &jump_ops, },
  61        { .name = "jnbe",       .ops = &jump_ops, },
  62        { .name = "jnc",        .ops = &jump_ops, },
  63        { .name = "jne",        .ops = &jump_ops, },
  64        { .name = "jng",        .ops = &jump_ops, },
  65        { .name = "jnge",       .ops = &jump_ops, },
  66        { .name = "jnl",        .ops = &jump_ops, },
  67        { .name = "jnle",       .ops = &jump_ops, },
  68        { .name = "jno",        .ops = &jump_ops, },
  69        { .name = "jnp",        .ops = &jump_ops, },
  70        { .name = "jns",        .ops = &jump_ops, },
  71        { .name = "jnz",        .ops = &jump_ops, },
  72        { .name = "jo",         .ops = &jump_ops, },
  73        { .name = "jp",         .ops = &jump_ops, },
  74        { .name = "jpe",        .ops = &jump_ops, },
  75        { .name = "jpo",        .ops = &jump_ops, },
  76        { .name = "jrcxz",      .ops = &jump_ops, },
  77        { .name = "js",         .ops = &jump_ops, },
  78        { .name = "jz",         .ops = &jump_ops, },
  79        { .name = "lea",        .ops = &mov_ops,  },
  80        { .name = "lock",       .ops = &lock_ops, },
  81        { .name = "mov",        .ops = &mov_ops,  },
  82        { .name = "movapd",     .ops = &mov_ops,  },
  83        { .name = "movaps",     .ops = &mov_ops,  },
  84        { .name = "movb",       .ops = &mov_ops,  },
  85        { .name = "movdqa",     .ops = &mov_ops,  },
  86        { .name = "movdqu",     .ops = &mov_ops,  },
  87        { .name = "movl",       .ops = &mov_ops,  },
  88        { .name = "movq",       .ops = &mov_ops,  },
  89        { .name = "movsd",      .ops = &mov_ops,  },
  90        { .name = "movslq",     .ops = &mov_ops,  },
  91        { .name = "movss",      .ops = &mov_ops,  },
  92        { .name = "movupd",     .ops = &mov_ops,  },
  93        { .name = "movups",     .ops = &mov_ops,  },
  94        { .name = "movw",       .ops = &mov_ops,  },
  95        { .name = "movzbl",     .ops = &mov_ops,  },
  96        { .name = "movzwl",     .ops = &mov_ops,  },
  97        { .name = "mulsd",      .ops = &mov_ops,  },
  98        { .name = "mulss",      .ops = &mov_ops,  },
  99        { .name = "nop",        .ops = &nop_ops,  },
 100        { .name = "nopl",       .ops = &nop_ops,  },
 101        { .name = "nopw",       .ops = &nop_ops,  },
 102        { .name = "or",         .ops = &mov_ops,  },
 103        { .name = "orb",        .ops = &mov_ops,  },
 104        { .name = "orl",        .ops = &mov_ops,  },
 105        { .name = "orps",       .ops = &mov_ops,  },
 106        { .name = "orq",        .ops = &mov_ops,  },
 107        { .name = "pand",       .ops = &mov_ops,  },
 108        { .name = "paddq",      .ops = &mov_ops,  },
 109        { .name = "pcmpeqb",    .ops = &mov_ops,  },
 110        { .name = "por",        .ops = &mov_ops,  },
 111        { .name = "rclb",       .ops = &mov_ops,  },
 112        { .name = "rcll",       .ops = &mov_ops,  },
 113        { .name = "retq",       .ops = &ret_ops,  },
 114        { .name = "sbb",        .ops = &mov_ops,  },
 115        { .name = "sbbl",       .ops = &mov_ops,  },
 116        { .name = "sete",       .ops = &mov_ops,  },
 117        { .name = "sub",        .ops = &mov_ops,  },
 118        { .name = "subl",       .ops = &mov_ops,  },
 119        { .name = "subq",       .ops = &mov_ops,  },
 120        { .name = "subsd",      .ops = &mov_ops,  },
 121        { .name = "subw",       .ops = &mov_ops,  },
 122        { .name = "test",       .ops = &mov_ops,  },
 123        { .name = "testb",      .ops = &mov_ops,  },
 124        { .name = "testl",      .ops = &mov_ops,  },
 125        { .name = "ucomisd",    .ops = &mov_ops,  },
 126        { .name = "ucomiss",    .ops = &mov_ops,  },
 127        { .name = "vaddsd",     .ops = &mov_ops,  },
 128        { .name = "vandpd",     .ops = &mov_ops,  },
 129        { .name = "vmovdqa",    .ops = &mov_ops,  },
 130        { .name = "vmovq",      .ops = &mov_ops,  },
 131        { .name = "vmovsd",     .ops = &mov_ops,  },
 132        { .name = "vmulsd",     .ops = &mov_ops,  },
 133        { .name = "vorpd",      .ops = &mov_ops,  },
 134        { .name = "vsubsd",     .ops = &mov_ops,  },
 135        { .name = "vucomisd",   .ops = &mov_ops,  },
 136        { .name = "xadd",       .ops = &mov_ops,  },
 137        { .name = "xbeginl",    .ops = &jump_ops, },
 138        { .name = "xbeginq",    .ops = &jump_ops, },
 139        { .name = "xchg",       .ops = &mov_ops,  },
 140        { .name = "xor",        .ops = &mov_ops, },
 141        { .name = "xorb",       .ops = &mov_ops, },
 142        { .name = "xorpd",      .ops = &mov_ops, },
 143        { .name = "xorps",      .ops = &mov_ops, },
 144};
 145
 146static bool x86__ins_is_fused(struct arch *arch, const char *ins1,
 147                              const char *ins2)
 148{
 149        if (arch->family != 6 || arch->model < 0x1e || strstr(ins2, "jmp"))
 150                return false;
 151
 152        if (arch->model == 0x1e) {
 153                /* Nehalem */
 154                if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
 155                     strstr(ins1, "test")) {
 156                        return true;
 157                }
 158        } else {
 159                /* Newer platform */
 160                if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
 161                     strstr(ins1, "test") ||
 162                     strstr(ins1, "add") ||
 163                     strstr(ins1, "sub") ||
 164                     strstr(ins1, "and") ||
 165                     strstr(ins1, "inc") ||
 166                     strstr(ins1, "dec")) {
 167                        return true;
 168                }
 169        }
 170
 171        return false;
 172}
 173
 174static int x86__cpuid_parse(struct arch *arch, char *cpuid)
 175{
 176        unsigned int family, model, stepping;
 177        int ret;
 178
 179        /*
 180         * cpuid = "GenuineIntel,family,model,stepping"
 181         */
 182        ret = sscanf(cpuid, "%*[^,],%u,%u,%u", &family, &model, &stepping);
 183        if (ret == 3) {
 184                arch->family = family;
 185                arch->model = model;
 186                return 0;
 187        }
 188
 189        return -1;
 190}
 191
 192static int x86__annotate_init(struct arch *arch, char *cpuid)
 193{
 194        int err = 0;
 195
 196        if (arch->initialized)
 197                return 0;
 198
 199        if (cpuid)
 200                err = x86__cpuid_parse(arch, cpuid);
 201
 202        arch->initialized = true;
 203        return err;
 204}
 205