hc
2024-08-16 a24a44ff9ca902811b99aa9663d697cf452e08ef
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// SPDX-License-Identifier: GPL-2.0
static struct ins x86__instructions[] = {
   { .name = "adc",    .ops = &mov_ops,  },
   { .name = "adcb",    .ops = &mov_ops,  },
   { .name = "adcl",    .ops = &mov_ops,  },
   { .name = "add",    .ops = &mov_ops,  },
   { .name = "addl",    .ops = &mov_ops,  },
   { .name = "addq",    .ops = &mov_ops,  },
   { .name = "addsd",    .ops = &mov_ops,  },
   { .name = "addw",    .ops = &mov_ops,  },
   { .name = "and",    .ops = &mov_ops,  },
   { .name = "andb",    .ops = &mov_ops,  },
   { .name = "andl",    .ops = &mov_ops,  },
   { .name = "andpd",    .ops = &mov_ops,  },
   { .name = "andps",    .ops = &mov_ops,  },
   { .name = "andq",    .ops = &mov_ops,  },
   { .name = "andw",    .ops = &mov_ops,  },
   { .name = "bsr",    .ops = &mov_ops,  },
   { .name = "bt",        .ops = &mov_ops,  },
   { .name = "btr",    .ops = &mov_ops,  },
   { .name = "bts",    .ops = &mov_ops,  },
   { .name = "btsq",    .ops = &mov_ops,  },
   { .name = "call",    .ops = &call_ops, },
   { .name = "callq",    .ops = &call_ops, },
   { .name = "cmovbe",    .ops = &mov_ops,  },
   { .name = "cmove",    .ops = &mov_ops,  },
   { .name = "cmovae",    .ops = &mov_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 = "cmpxchg",    .ops = &mov_ops,  },
   { .name = "cs",        .ops = &mov_ops,  },
   { .name = "dec",    .ops = &dec_ops,  },
   { .name = "decl",    .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 = "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 = "movapd",    .ops = &mov_ops,  },
   { .name = "movaps",    .ops = &mov_ops,  },
   { .name = "movb",    .ops = &mov_ops,  },
   { .name = "movdqa",    .ops = &mov_ops,  },
   { .name = "movdqu",    .ops = &mov_ops,  },
   { .name = "movl",    .ops = &mov_ops,  },
   { .name = "movq",    .ops = &mov_ops,  },
   { .name = "movsd",    .ops = &mov_ops,  },
   { .name = "movslq",    .ops = &mov_ops,  },
   { .name = "movss",    .ops = &mov_ops,  },
   { .name = "movupd",    .ops = &mov_ops,  },
   { .name = "movups",    .ops = &mov_ops,  },
   { .name = "movw",    .ops = &mov_ops,  },
   { .name = "movzbl",    .ops = &mov_ops,  },
   { .name = "movzwl",    .ops = &mov_ops,  },
   { .name = "mulsd",    .ops = &mov_ops,  },
   { .name = "mulss",    .ops = &mov_ops,  },
   { .name = "nop",    .ops = &nop_ops,  },
   { .name = "nopl",    .ops = &nop_ops,  },
   { .name = "nopw",    .ops = &nop_ops,  },
   { .name = "or",        .ops = &mov_ops,  },
   { .name = "orb",    .ops = &mov_ops,  },
   { .name = "orl",    .ops = &mov_ops,  },
   { .name = "orps",    .ops = &mov_ops,  },
   { .name = "orq",    .ops = &mov_ops,  },
   { .name = "pand",    .ops = &mov_ops,  },
   { .name = "paddq",    .ops = &mov_ops,  },
   { .name = "pcmpeqb",    .ops = &mov_ops,  },
   { .name = "por",    .ops = &mov_ops,  },
   { .name = "rclb",    .ops = &mov_ops,  },
   { .name = "rcll",    .ops = &mov_ops,  },
   { .name = "ret",    .ops = &ret_ops,  },
   { .name = "retq",    .ops = &ret_ops,  },
   { .name = "sbb",    .ops = &mov_ops,  },
   { .name = "sbbl",    .ops = &mov_ops,  },
   { .name = "sete",    .ops = &mov_ops,  },
   { .name = "sub",    .ops = &mov_ops,  },
   { .name = "subl",    .ops = &mov_ops,  },
   { .name = "subq",    .ops = &mov_ops,  },
   { .name = "subsd",    .ops = &mov_ops,  },
   { .name = "subw",    .ops = &mov_ops,  },
   { .name = "test",    .ops = &mov_ops,  },
   { .name = "testb",    .ops = &mov_ops,  },
   { .name = "testl",    .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 = "xbeginl",    .ops = &jump_ops, },
   { .name = "xbeginq",    .ops = &jump_ops, },
   { .name = "xchg",    .ops = &mov_ops,  },
   { .name = "xor",    .ops = &mov_ops, },
   { .name = "xorb",    .ops = &mov_ops, },
   { .name = "xorpd",    .ops = &mov_ops, },
   { .name = "xorps",    .ops = &mov_ops, },
};
 
static bool x86__ins_is_fused(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;
       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;
   }
 
   arch->initialized = true;
   return err;
}