~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/arch/x86/annotate/instructions.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * x86 instruction nmemonic table to parse disasm lines for annotate.
  4  * This table is searched twice - one for exact match and another for
  5  * match without a size suffix (b, w, l, q) in case of AT&T syntax.
  6  *
  7  * So this table should not have entries with the suffix unless it's
  8  * a complete different instruction than ones without the suffix.
  9  */
 10 static struct ins x86__instructions[] = {
 11         { .name = "adc",        .ops = &mov_ops,  },
 12         { .name = "add",        .ops = &mov_ops,  },
 13         { .name = "addsd",      .ops = &mov_ops,  },
 14         { .name = "and",        .ops = &mov_ops,  },
 15         { .name = "andpd",      .ops = &mov_ops,  },
 16         { .name = "andps",      .ops = &mov_ops,  },
 17         { .name = "bsr",        .ops = &mov_ops,  },
 18         { .name = "bt",         .ops = &mov_ops,  },
 19         { .name = "btr",        .ops = &mov_ops,  },
 20         { .name = "bts",        .ops = &mov_ops,  },
 21         { .name = "call",       .ops = &call_ops, },
 22         { .name = "cmovbe",     .ops = &mov_ops,  },
 23         { .name = "cmove",      .ops = &mov_ops,  },
 24         { .name = "cmovae",     .ops = &mov_ops,  },
 25         { .name = "cmp",        .ops = &mov_ops,  },
 26         { .name = "cmpxch",     .ops = &mov_ops,  },
 27         { .name = "cmpxchg",    .ops = &mov_ops,  },
 28         { .name = "cs",         .ops = &mov_ops,  },
 29         { .name = "dec",        .ops = &dec_ops,  },
 30         { .name = "divsd",      .ops = &mov_ops,  },
 31         { .name = "divss",      .ops = &mov_ops,  },
 32         { .name = "gs",         .ops = &mov_ops,  },
 33         { .name = "imul",       .ops = &mov_ops,  },
 34         { .name = "inc",        .ops = &dec_ops,  },
 35         { .name = "ja",         .ops = &jump_ops, },
 36         { .name = "jae",        .ops = &jump_ops, },
 37         { .name = "jb",         .ops = &jump_ops, },
 38         { .name = "jbe",        .ops = &jump_ops, },
 39         { .name = "jc",         .ops = &jump_ops, },
 40         { .name = "jcxz",       .ops = &jump_ops, },
 41         { .name = "je",         .ops = &jump_ops, },
 42         { .name = "jecxz",      .ops = &jump_ops, },
 43         { .name = "jg",         .ops = &jump_ops, },
 44         { .name = "jge",        .ops = &jump_ops, },
 45         { .name = "jl",         .ops = &jump_ops, },
 46         { .name = "jle",        .ops = &jump_ops, },
 47         { .name = "jmp",        .ops = &jump_ops, },
 48         { .name = "jna",        .ops = &jump_ops, },
 49         { .name = "jnae",       .ops = &jump_ops, },
 50         { .name = "jnb",        .ops = &jump_ops, },
 51         { .name = "jnbe",       .ops = &jump_ops, },
 52         { .name = "jnc",        .ops = &jump_ops, },
 53         { .name = "jne",        .ops = &jump_ops, },
 54         { .name = "jng",        .ops = &jump_ops, },
 55         { .name = "jnge",       .ops = &jump_ops, },
 56         { .name = "jnl",        .ops = &jump_ops, },
 57         { .name = "jnle",       .ops = &jump_ops, },
 58         { .name = "jno",        .ops = &jump_ops, },
 59         { .name = "jnp",        .ops = &jump_ops, },
 60         { .name = "jns",        .ops = &jump_ops, },
 61         { .name = "jnz",        .ops = &jump_ops, },
 62         { .name = "jo",         .ops = &jump_ops, },
 63         { .name = "jp",         .ops = &jump_ops, },
 64         { .name = "jpe",        .ops = &jump_ops, },
 65         { .name = "jpo",        .ops = &jump_ops, },
 66         { .name = "jrcxz",      .ops = &jump_ops, },
 67         { .name = "js",         .ops = &jump_ops, },
 68         { .name = "jz",         .ops = &jump_ops, },
 69         { .name = "lea",        .ops = &mov_ops,  },
 70         { .name = "lock",       .ops = &lock_ops, },
 71         { .name = "mov",        .ops = &mov_ops,  },
 72         { .name = "movapd",     .ops = &mov_ops,  },
 73         { .name = "movaps",     .ops = &mov_ops,  },
 74         { .name = "movdqa",     .ops = &mov_ops,  },
 75         { .name = "movdqu",     .ops = &mov_ops,  },
 76         { .name = "movsd",      .ops = &mov_ops,  },
 77         { .name = "movss",      .ops = &mov_ops,  },
 78         { .name = "movsb",      .ops = &mov_ops,  },
 79         { .name = "movsw",      .ops = &mov_ops,  },
 80         { .name = "movsl",      .ops = &mov_ops,  },
 81         { .name = "movupd",     .ops = &mov_ops,  },
 82         { .name = "movups",     .ops = &mov_ops,  },
 83         { .name = "movzb",      .ops = &mov_ops,  },
 84         { .name = "movzw",      .ops = &mov_ops,  },
 85         { .name = "movzl",      .ops = &mov_ops,  },
 86         { .name = "mulsd",      .ops = &mov_ops,  },
 87         { .name = "mulss",      .ops = &mov_ops,  },
 88         { .name = "nop",        .ops = &nop_ops,  },
 89         { .name = "or",         .ops = &mov_ops,  },
 90         { .name = "orps",       .ops = &mov_ops,  },
 91         { .name = "pand",       .ops = &mov_ops,  },
 92         { .name = "paddq",      .ops = &mov_ops,  },
 93         { .name = "pcmpeqb",    .ops = &mov_ops,  },
 94         { .name = "por",        .ops = &mov_ops,  },
 95         { .name = "rcl",        .ops = &mov_ops,  },
 96         { .name = "ret",        .ops = &ret_ops,  },
 97         { .name = "sbb",        .ops = &mov_ops,  },
 98         { .name = "sete",       .ops = &mov_ops,  },
 99         { .name = "sub",        .ops = &mov_ops,  },
100         { .name = "subsd",      .ops = &mov_ops,  },
101         { .name = "test",       .ops = &mov_ops,  },
102         { .name = "tzcnt",      .ops = &mov_ops,  },
103         { .name = "ucomisd",    .ops = &mov_ops,  },
104         { .name = "ucomiss",    .ops = &mov_ops,  },
105         { .name = "vaddsd",     .ops = &mov_ops,  },
106         { .name = "vandpd",     .ops = &mov_ops,  },
107         { .name = "vmovdqa",    .ops = &mov_ops,  },
108         { .name = "vmovq",      .ops = &mov_ops,  },
109         { .name = "vmovsd",     .ops = &mov_ops,  },
110         { .name = "vmulsd",     .ops = &mov_ops,  },
111         { .name = "vorpd",      .ops = &mov_ops,  },
112         { .name = "vsubsd",     .ops = &mov_ops,  },
113         { .name = "vucomisd",   .ops = &mov_ops,  },
114         { .name = "xadd",       .ops = &mov_ops,  },
115         { .name = "xbegin",     .ops = &jump_ops, },
116         { .name = "xchg",       .ops = &mov_ops,  },
117         { .name = "xor",        .ops = &mov_ops, },
118         { .name = "xorpd",      .ops = &mov_ops, },
119         { .name = "xorps",      .ops = &mov_ops, },
120 };
121 
122 static bool amd__ins_is_fused(struct arch *arch, const char *ins1,
123                               const char *ins2)
124 {
125         if (strstr(ins2, "jmp"))
126                 return false;
127 
128         /* Family >= 15h supports cmp/test + branch fusion */
129         if (arch->family >= 0x15 && (strstarts(ins1, "test") ||
130             (strstarts(ins1, "cmp") && !strstr(ins1, "xchg")))) {
131                 return true;
132         }
133 
134         /* Family >= 19h supports some ALU + branch fusion */
135         if (arch->family >= 0x19 && (strstarts(ins1, "add") ||
136             strstarts(ins1, "sub") || strstarts(ins1, "and") ||
137             strstarts(ins1, "inc") || strstarts(ins1, "dec") ||
138             strstarts(ins1, "or") || strstarts(ins1, "xor"))) {
139                 return true;
140         }
141 
142         return false;
143 }
144 
145 static bool intel__ins_is_fused(struct arch *arch, const char *ins1,
146                                 const char *ins2)
147 {
148         if (arch->family != 6 || arch->model < 0x1e || strstr(ins2, "jmp"))
149                 return false;
150 
151         if (arch->model == 0x1e) {
152                 /* Nehalem */
153                 if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
154                      strstr(ins1, "test")) {
155                         return true;
156                 }
157         } else {
158                 /* Newer platform */
159                 if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
160                      strstr(ins1, "test") ||
161                      strstr(ins1, "add") ||
162                      strstr(ins1, "sub") ||
163                      strstr(ins1, "and") ||
164                      strstr(ins1, "inc") ||
165                      strstr(ins1, "dec")) {
166                         return true;
167                 }
168         }
169 
170         return false;
171 }
172 
173 static int x86__cpuid_parse(struct arch *arch, char *cpuid)
174 {
175         unsigned int family, model, stepping;
176         int ret;
177 
178         /*
179          * cpuid = "GenuineIntel,family,model,stepping"
180          */
181         ret = sscanf(cpuid, "%*[^,],%u,%u,%u", &family, &model, &stepping);
182         if (ret == 3) {
183                 arch->family = family;
184                 arch->model = model;
185                 arch->ins_is_fused = strstarts(cpuid, "AuthenticAMD") ?
186                                         amd__ins_is_fused :
187                                         intel__ins_is_fused;
188                 return 0;
189         }
190 
191         return -1;
192 }
193 
194 static int x86__annotate_init(struct arch *arch, char *cpuid)
195 {
196         int err = 0;
197 
198         if (arch->initialized)
199                 return 0;
200 
201         if (cpuid) {
202                 if (x86__cpuid_parse(arch, cpuid))
203                         err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
204         }
205 
206         arch->initialized = true;
207         return err;
208 }
209 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php