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